element: Remove IPv4
[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         service = __connman_service_lookup_from_network(network);
565         if (service == NULL)
566                 return;
567
568         ipconfig = __connman_service_get_ip4config(service);
569         if (ipconfig == NULL)
570                 return;
571
572         connman_ipconfig_set_method(ipconfig, method);
573 }
574
575 void connman_network_set_ipv6_method(struct connman_network *network,
576                                         enum connman_ipconfig_method method)
577 {
578         struct connman_service *service;
579         struct connman_ipconfig *ipconfig;
580
581         network->element.ipv6.method = method;
582
583         service = __connman_service_lookup_from_network(network);
584         if (service == NULL)
585                 return;
586
587         ipconfig = __connman_service_get_ip6config(service);
588         if (ipconfig == NULL)
589                 return;
590
591         connman_ipconfig_set_method(ipconfig, method);
592 }
593
594 void connman_network_set_error(struct connman_network *network,
595                                         enum connman_network_error error)
596 {
597         DBG("nework %p, error %d", network, error);
598
599         network->connecting = FALSE;
600
601         switch (error) {
602         case CONNMAN_NETWORK_ERROR_UNKNOWN:
603                 return;
604         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
605                 set_associate_error(network);
606                 break;
607         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
608                 set_configure_error(network);
609                 break;
610         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
611                 set_invalid_key_error(network);
612                 break;
613         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
614                 set_connect_error(network);
615                 break;
616         }
617 }
618
619 void connman_network_clear_error(struct connman_network *network)
620 {
621         struct connman_service *service;
622
623         DBG("network %p", network);
624
625         if (network == NULL)
626                 return;
627
628         if (network->connecting == TRUE || network->associating == TRUE)
629                 return;
630
631         service = __connman_service_lookup_from_network(network);
632         __connman_service_clear_error(service);
633 }
634
635 static void set_configuration(struct connman_network *network)
636 {
637         struct connman_service *service;
638
639         DBG("network %p", network);
640
641         __connman_device_increase_connections(network->device);
642
643         __connman_device_set_network(network->device, network);
644
645         connman_device_set_disconnected(network->device, FALSE);
646
647         service = __connman_service_lookup_from_network(network);
648         __connman_service_indicate_state(service,
649                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
650                                         CONNMAN_IPCONFIG_TYPE_IPV4);
651 }
652
653 static void dhcp_success(struct connman_network *network)
654 {
655         struct connman_service *service;
656         struct connman_ipconfig *ipconfig_ipv4;
657         int err;
658
659         service = __connman_service_lookup_from_network(network);
660         if (service == NULL)
661                 goto err;
662
663         connman_network_set_associating(network, FALSE);
664
665         network->connecting = FALSE;
666
667         ipconfig_ipv4 = __connman_service_get_ip4config(service);
668         err = __connman_ipconfig_address_add(ipconfig_ipv4);
669         if (err < 0)
670                 goto err;
671
672         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
673         if (err < 0)
674                 goto err;
675
676         __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
677                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
678
679         return;
680
681 err:
682         connman_network_set_error(network,
683                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
684 }
685
686 static void dhcp_failure(struct connman_network *network)
687 {
688         struct connman_service *service;
689         struct connman_ipconfig *ipconfig_ipv4;
690
691         service = __connman_service_lookup_from_network(network);
692         if (service == NULL)
693                 return;
694
695         ipconfig_ipv4 = __connman_service_get_ip4config(service);
696         __connman_ipconfig_address_remove(ipconfig_ipv4);
697
698         __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_IDLE,
699                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
700 }
701
702 static void dhcp_callback(struct connman_network *network,
703                         connman_bool_t success)
704 {
705         DBG("success %d", success);
706
707         if (success == TRUE)
708                 dhcp_success(network);
709         else
710                 dhcp_failure(network);
711 }
712
713 static int set_connected_fixed(struct connman_network *network)
714 {
715         struct connman_service *service;
716         struct connman_ipconfig *ipconfig_ipv4;
717         int err;
718
719         DBG("");
720
721         service = __connman_service_lookup_from_network(network);
722
723         ipconfig_ipv4 = __connman_service_get_ip4config(service);
724
725         set_configuration(network);
726
727         network->connecting = FALSE;
728
729         connman_network_set_associating(network, FALSE);
730
731         err = __connman_ipconfig_address_add(ipconfig_ipv4);
732         if (err < 0)
733                 goto err;
734
735         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
736         if (err < 0)
737                 goto err;
738
739         __connman_service_indicate_state(service,
740                                         CONNMAN_SERVICE_STATE_READY,
741                                         CONNMAN_IPCONFIG_TYPE_IPV4);
742         return 0;
743
744 err:
745         connman_network_set_error(network,
746                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
747
748         return err;
749 }
750
751 static void set_connected_manual(struct connman_network *network)
752 {
753         struct connman_service *service;
754         struct connman_ipconfig *ipconfig;
755         int err;
756
757         DBG("network %p", network);
758
759         service = __connman_service_lookup_from_network(network);
760
761         ipconfig = __connman_service_get_ip4config(service);
762
763         set_configuration(network);
764
765         err = __connman_ipconfig_address_add(ipconfig);
766         if (err < 0)
767                 goto err;
768
769         err = __connman_ipconfig_gateway_add(ipconfig);
770         if (err < 0)
771                 goto err;
772
773         network->connecting = FALSE;
774
775         connman_network_set_associating(network, FALSE);
776
777         __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
778                                         CONNMAN_IPCONFIG_TYPE_IPV4);
779
780         return;
781
782 err:
783         connman_network_set_error(network,
784                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
785         return;
786 }
787
788 static int set_connected_dhcp(struct connman_network *network)
789 {
790         int err;
791
792         DBG("network %p", network);
793
794         set_configuration(network);
795
796         err = __connman_dhcp_start(network, dhcp_callback);
797         if (err < 0) {
798                 connman_error("Can not request DHCP lease");
799                 return err;
800         }
801
802         return 0;
803 }
804
805 static int manual_ipv6_set(struct connman_network *network,
806                                 struct connman_ipconfig *ipconfig_ipv6)
807 {
808         struct connman_service *service;
809         int err;
810
811         service = __connman_service_lookup_from_network(network);
812         if (service == NULL)
813                 return -EINVAL;
814
815         err = __connman_ipconfig_address_add(ipconfig_ipv6);
816         if (err < 0) {
817                 connman_network_set_error(network,
818                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
819                 return err;
820         }
821
822         /*
823          * READY state will be indicated by IPV4 setting
824          * gateway will be set by IPV4 setting
825          */
826
827         return 0;
828 }
829
830 static void autoconf_ipv6_set(struct connman_network *network)
831 {
832         struct connman_service *service;
833         const char *nameserver = NULL;
834
835         DBG("network %p", network);
836
837         service = __connman_service_lookup_from_network(network);
838
839         __connman_device_increase_connections(network->device);
840
841         __connman_device_set_network(network->device, network);
842
843         connman_device_set_disconnected(network->device, FALSE);
844
845         connman_element_get_value(&network->element,
846                         CONNMAN_PROPERTY_ID_IPV6_NAMESERVER, &nameserver);
847         if (nameserver != NULL)
848                 __connman_service_nameserver_append(service, nameserver);
849
850         network->connecting = FALSE;
851
852         __connman_service_indicate_state(service,
853                                         CONNMAN_SERVICE_STATE_READY,
854                                         CONNMAN_IPCONFIG_TYPE_IPV6);
855 }
856
857 static gboolean set_connected(gpointer user_data)
858 {
859         struct connman_network *network = user_data;
860         struct connman_service *service;
861         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
862         enum connman_ipconfig_method ipv4_method, ipv6_method;
863
864         service = __connman_service_lookup_from_network(network);
865
866         ipconfig_ipv4 = __connman_service_get_ip4config(service);
867         ipconfig_ipv6 = __connman_service_get_ip6config(service);
868
869         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
870                 ipconfig_ipv6);
871
872         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
873         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
874
875         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
876         DBG("network connected %d", network->connected);
877
878         if (network->connected == TRUE) {
879                 int ret;
880
881                 switch (ipv6_method) {
882                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
883                 case CONNMAN_IPCONFIG_METHOD_OFF:
884                         break;
885                 case CONNMAN_IPCONFIG_METHOD_AUTO:
886                         autoconf_ipv6_set(network);
887                         break;
888                 case CONNMAN_IPCONFIG_METHOD_FIXED:
889                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
890                         ret = manual_ipv6_set(network, ipconfig_ipv6);
891                         if (ret != 0) {
892                                 connman_network_set_error(network,
893                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
894                                 return FALSE;
895                         }
896                         break;
897                 case CONNMAN_IPCONFIG_METHOD_DHCP:
898                         break;
899                 }
900
901                 switch (ipv4_method) {
902                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
903                 case CONNMAN_IPCONFIG_METHOD_OFF:
904                 case CONNMAN_IPCONFIG_METHOD_AUTO:
905                         return FALSE;
906                 case CONNMAN_IPCONFIG_METHOD_FIXED:
907                         if (set_connected_fixed(network) < 0) {
908                                 connman_network_set_error(network,
909                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
910                                 return FALSE;
911                         }
912                         return TRUE;
913                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
914                         set_connected_manual(network);
915                         return TRUE;
916                 case CONNMAN_IPCONFIG_METHOD_DHCP:
917                         if (set_connected_dhcp(network) < 0) {
918                                 connman_network_set_error(network,
919                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
920                                 return FALSE;
921                         }
922                 }
923
924         } else {
925                 struct connman_service *service;
926
927                 connman_element_unregister_children(&network->element);
928
929                 __connman_device_set_network(network->device, NULL);
930                 network->hidden = FALSE;
931
932                 service = __connman_service_lookup_from_network(network);
933
934                 __connman_service_indicate_state(service,
935                                         CONNMAN_SERVICE_STATE_DISCONNECT,
936                                         CONNMAN_IPCONFIG_TYPE_IPV4);
937
938                 __connman_service_indicate_state(service,
939                                         CONNMAN_SERVICE_STATE_DISCONNECT,
940                                         CONNMAN_IPCONFIG_TYPE_IPV6);
941
942                 __connman_connection_gateway_remove(service);
943
944                 __connman_service_indicate_state(service,
945                                         CONNMAN_SERVICE_STATE_IDLE,
946                                         CONNMAN_IPCONFIG_TYPE_IPV4);
947
948                 __connman_service_indicate_state(service,
949                                         CONNMAN_SERVICE_STATE_IDLE,
950                                         CONNMAN_IPCONFIG_TYPE_IPV6);
951         }
952
953         network->connecting = FALSE;
954
955         connman_network_set_associating(network, FALSE);
956
957         return FALSE;
958 }
959
960 /**
961  * connman_network_set_connected:
962  * @network: network structure
963  * @connected: connected state
964  *
965  * Change connected state of network
966  */
967 int connman_network_set_connected(struct connman_network *network,
968                                                 connman_bool_t connected)
969 {
970         DBG("network %p connected %d", network, connected);
971
972         if ((network->connecting == TRUE || network->associating == TRUE) &&
973                                                         connected == FALSE) {
974                 connman_network_set_error(network,
975                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
976                 __connman_network_disconnect(network);
977         }
978
979         if (network->connected == connected)
980                 return -EALREADY;
981
982         if (connected == FALSE)
983                 __connman_device_decrease_connections(network->device);
984
985         network->connected = connected;
986
987         set_connected(network);
988
989         return 0;
990 }
991
992 /**
993  * connman_network_get_connected:
994  * @network: network structure
995  *
996  * Get network connection status
997  */
998 connman_bool_t connman_network_get_connected(struct connman_network *network)
999 {
1000         return network->connected;
1001 }
1002
1003 /**
1004  * connman_network_get_associating:
1005  * @network: network structure
1006  *
1007  * Get network associating status
1008  */
1009 connman_bool_t connman_network_get_associating(struct connman_network *network)
1010 {
1011         return network->associating;
1012 }
1013
1014 /**
1015  * __connman_network_connect:
1016  * @network: network structure
1017  *
1018  * Connect network
1019  */
1020 int __connman_network_connect(struct connman_network *network)
1021 {
1022         int err;
1023
1024         DBG("network %p", network);
1025
1026         if (network->connected == TRUE)
1027                 return -EISCONN;
1028
1029         if (network->connecting == TRUE || network->associating == TRUE)
1030                 return -EALREADY;
1031
1032         if (network->driver == NULL)
1033                 return -EUNATCH;
1034
1035         if (network->driver->connect == NULL)
1036                 return -ENOSYS;
1037
1038         if (network->device == NULL)
1039                 return -ENODEV;
1040
1041         network->connecting = TRUE;
1042
1043         __connman_device_disconnect(network->device);
1044
1045         err = network->driver->connect(network);
1046         if (err < 0) {
1047                 if (err == -EINPROGRESS)
1048                         connman_network_set_associating(network, TRUE);
1049                 else {
1050                         network->connecting = FALSE;
1051                         network->hidden = FALSE;
1052                 }
1053
1054                 return err;
1055         }
1056
1057         network->connected = TRUE;
1058         set_connected(network);
1059
1060         return err;
1061 }
1062
1063 /**
1064  * __connman_network_disconnect:
1065  * @network: network structure
1066  *
1067  * Disconnect network
1068  */
1069 int __connman_network_disconnect(struct connman_network *network)
1070 {
1071         int err;
1072
1073         DBG("network %p", network);
1074
1075         if (network->connected == FALSE && network->connecting == FALSE &&
1076                                                 network->associating == FALSE)
1077                 return -ENOTCONN;
1078
1079         if (network->driver == NULL)
1080                 return -EUNATCH;
1081
1082         if (network->driver->disconnect == NULL)
1083                 return -ENOSYS;
1084
1085         network->connecting = FALSE;
1086
1087         err = network->driver->disconnect(network);
1088         if (err == 0) {
1089                 connman_network_set_connected(network, FALSE);
1090                 set_connected(network);
1091         }
1092
1093         return err;
1094 }
1095
1096 static int manual_ipv4_set(struct connman_network *network,
1097                                 struct connman_ipconfig *ipconfig)
1098 {
1099         struct connman_service *service;
1100         int err;
1101
1102         service = __connman_service_lookup_from_network(network);
1103         if (service == NULL)
1104                 return -EINVAL;
1105
1106         err = __connman_ipconfig_address_add(ipconfig);
1107         if (err < 0) {
1108                 connman_network_set_error(network,
1109                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1110                 return err;
1111         }
1112
1113         __connman_ipconfig_gateway_add(ipconfig);
1114
1115         __connman_service_indicate_state(service, CONNMAN_SERVICE_STATE_READY,
1116                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1117
1118         return 0;
1119 }
1120
1121 int __connman_network_clear_ipconfig(struct connman_network *network,
1122                                         struct connman_ipconfig *ipconfig)
1123 {
1124         struct connman_service *service;
1125         enum connman_ipconfig_method method;
1126         enum connman_ipconfig_type type;
1127
1128         service = __connman_service_lookup_from_network(network);
1129         if (service == NULL)
1130                 return -EINVAL;
1131
1132         method = __connman_ipconfig_get_method(ipconfig);
1133         type = __connman_ipconfig_get_config_type(ipconfig);
1134
1135         switch (method) {
1136         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1137         case CONNMAN_IPCONFIG_METHOD_OFF:
1138         case CONNMAN_IPCONFIG_METHOD_FIXED:
1139         case CONNMAN_IPCONFIG_METHOD_AUTO:
1140                 return -EINVAL;
1141         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1142                 __connman_ipconfig_address_remove(ipconfig);
1143                 break;
1144         case CONNMAN_IPCONFIG_METHOD_DHCP:
1145                 __connman_dhcp_stop(network);
1146                 break;
1147         }
1148
1149         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1150                 __connman_service_indicate_state(service,
1151                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1152                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1153         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1154                 __connman_service_indicate_state(service,
1155                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1156                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1157
1158         return 0;
1159 }
1160
1161 int __connman_network_set_ipconfig(struct connman_network *network,
1162                                         struct connman_ipconfig *ipconfig_ipv4,
1163                                         struct connman_ipconfig *ipconfig_ipv6)
1164 {
1165         enum connman_ipconfig_method method;
1166         int ret;
1167
1168         if (ipconfig_ipv6) {
1169                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1170
1171                 switch (method) {
1172                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1173                 case CONNMAN_IPCONFIG_METHOD_OFF:
1174                         break;
1175                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1176                         autoconf_ipv6_set(network);
1177                         break;
1178                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1179                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1180                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1181                         if (ret != 0) {
1182                                 connman_network_set_error(network,
1183                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1184                                 return ret;
1185                         }
1186                         break;
1187                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1188                         break;
1189                 }
1190         }
1191
1192         if (ipconfig_ipv4) {
1193                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1194
1195                 switch (method) {
1196                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1197                 case CONNMAN_IPCONFIG_METHOD_OFF:
1198                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1199                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1200                         return -EINVAL;
1201                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1202                         return manual_ipv4_set(network, ipconfig_ipv4);
1203                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1204                         return __connman_dhcp_start(network, dhcp_callback);
1205                 }
1206         }
1207
1208         return 0;
1209 }
1210
1211 int connman_network_set_ipaddress(struct connman_network *network,
1212                                         struct connman_ipaddress *ipaddress)
1213 {
1214         struct connman_service *service;
1215         struct connman_ipconfig *ipconfig = NULL;
1216
1217         DBG("network %p", network);
1218
1219         service = __connman_service_lookup_from_network(network);
1220         if (service == NULL)
1221                 return -EINVAL;
1222
1223         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1224         if (ipconfig == NULL)
1225                 return -EINVAL;
1226
1227         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1228         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1229         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1230         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1231         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1232
1233         return 0;
1234 }
1235
1236 int connman_network_set_pac(struct connman_network *network,
1237                                 const char *pac)
1238 {
1239         struct connman_service *service;
1240
1241         DBG("network %p pac %s", network, pac);
1242
1243         service = __connman_service_lookup_from_network(network);
1244         if (service == NULL)
1245                 return -EINVAL;
1246
1247         __connman_service_set_pac(service, pac);
1248
1249         return 0;
1250 }
1251
1252 int connman_network_set_nameservers(struct connman_network *network,
1253                                 const char *nameservers)
1254 {
1255         struct connman_service *service;
1256         char **nameservers_array = NULL;
1257         int i;
1258
1259         DBG("network %p nameservers %s", network, nameservers);
1260
1261         service = __connman_service_lookup_from_network(network);
1262         if (service == NULL)
1263                 return -EINVAL;
1264
1265         __connman_service_nameserver_clear(service);
1266
1267         if (nameservers != NULL)
1268                 nameservers_array = g_strsplit(nameservers, " ", 0);
1269
1270         for (i = 0; nameservers_array[i] != NULL; i++) {
1271                 __connman_service_nameserver_append(service,
1272                                                 nameservers_array[i]);
1273         }
1274
1275         g_strfreev(nameservers_array);
1276
1277         return 0;
1278 }
1279
1280 int connman_network_set_domain(struct connman_network *network,
1281                                 const char *domain)
1282 {
1283         struct connman_service *service;
1284
1285         DBG("network %p domain %s", network, domain);
1286
1287         service = __connman_service_lookup_from_network(network);
1288         if (service == NULL)
1289                 return -EINVAL;
1290
1291         __connman_service_set_domainname(service, domain);
1292
1293         return 0;
1294 }
1295
1296 /**
1297  * connman_network_set_name:
1298  * @network: network structure
1299  * @name: name value
1300  *
1301  * Set display name value for network
1302  */
1303 int connman_network_set_name(struct connman_network *network,
1304                                                         const char *name)
1305 {
1306         DBG("network %p name %s", network, name);
1307
1308         g_free(network->name);
1309         network->name = g_strdup(name);
1310
1311         return connman_element_set_string(&network->element, "Name", name);
1312 }
1313
1314 /**
1315  * connman_network_set_strength:
1316  * @network: network structure
1317  * @strength: strength value
1318  *
1319  * Set signal strength value for network
1320  */
1321 int connman_network_set_strength(struct connman_network *network,
1322                                                 connman_uint8_t strength)
1323 {
1324         DBG("network %p strengh %d", network, strength);
1325
1326         network->strength = strength;
1327
1328         return connman_element_set_uint8(&network->element,
1329                                                 "Strength", strength);
1330 }
1331
1332 /**
1333  * connman_network_set_roaming:
1334  * @network: network structure
1335  * @roaming: roaming state
1336  *
1337  * Set roaming state for network
1338  */
1339 int connman_network_set_roaming(struct connman_network *network,
1340                                                 connman_bool_t roaming)
1341 {
1342         DBG("network %p roaming %d", network, roaming);
1343
1344         network->roaming = roaming;
1345
1346         return connman_element_set_bool(&network->element,
1347                                                 "Roaming", roaming);
1348 }
1349
1350 /**
1351  * connman_network_set_string:
1352  * @network: network structure
1353  * @key: unique identifier
1354  * @value: string value
1355  *
1356  * Set string value for specific key
1357  */
1358 int connman_network_set_string(struct connman_network *network,
1359                                         const char *key, const char *value)
1360 {
1361         int err;
1362
1363         DBG("network %p key %s value %s", network, key, value);
1364
1365         if (g_strcmp0(key, "Name") == 0)
1366                 return connman_network_set_name(network, value);
1367
1368         if (g_str_equal(key, "Node") == TRUE) {
1369                 g_free(network->node);
1370                 network->node = g_strdup(value);
1371         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1372                 g_free(network->wifi.mode);
1373                 network->wifi.mode = g_strdup(value);
1374         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1375                 g_free(network->wifi.security);
1376                 network->wifi.security = g_strdup(value);
1377         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1378                 g_free(network->wifi.passphrase);
1379                 network->wifi.passphrase = g_strdup(value);
1380         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1381                 g_free(network->wifi.eap);
1382                 network->wifi.eap = g_strdup(value);
1383         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1384                 g_free(network->wifi.identity);
1385                 network->wifi.identity = g_strdup(value);
1386         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1387                 g_free(network->wifi.ca_cert_path);
1388                 network->wifi.ca_cert_path = g_strdup(value);
1389         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1390                 g_free(network->wifi.client_cert_path);
1391                 network->wifi.client_cert_path = g_strdup(value);
1392         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1393                 g_free(network->wifi.private_key_path);
1394                 network->wifi.private_key_path = g_strdup(value);
1395         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1396                 g_free(network->wifi.private_key_passphrase);
1397                 network->wifi.private_key_passphrase = g_strdup(value);
1398         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1399                 g_free(network->wifi.phase2_auth);
1400                 network->wifi.phase2_auth = g_strdup(value);
1401         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1402                 g_free(network->wifi.pin_wps);
1403                 network->wifi.pin_wps = g_strdup(value);
1404         }
1405
1406         err = connman_element_set_string(&network->element, key, value);
1407         if (err < 0)
1408                 return err;
1409
1410         if (network->driver == NULL)
1411                 return 0;
1412
1413         if (network->driver->setup)
1414                 return network->driver->setup(network, key);
1415
1416         return 0;
1417 }
1418
1419 /**
1420  * connman_network_get_string:
1421  * @network: network structure
1422  * @key: unique identifier
1423  *
1424  * Get string value for specific key
1425  */
1426 const char *connman_network_get_string(struct connman_network *network,
1427                                                         const char *key)
1428 {
1429         DBG("network %p key %s", network, key);
1430
1431         if (g_str_equal(key, "Name") == TRUE)
1432                 return network->name;
1433         else if (g_str_equal(key, "Node") == TRUE)
1434                 return network->node;
1435         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1436                 return network->wifi.mode;
1437         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1438                 return network->wifi.security;
1439         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1440                 return network->wifi.passphrase;
1441         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1442                 return network->wifi.eap;
1443         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1444                 return network->wifi.identity;
1445         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1446                 return network->wifi.ca_cert_path;
1447         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1448                 return network->wifi.client_cert_path;
1449         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1450                 return network->wifi.private_key_path;
1451         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1452                 return network->wifi.private_key_passphrase;
1453         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1454                 return network->wifi.phase2_auth;
1455         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1456                 return network->wifi.pin_wps;
1457
1458         return connman_element_get_string(&network->element, key);
1459 }
1460
1461 /**
1462  * connman_network_set_bool:
1463  * @network: network structure
1464  * @key: unique identifier
1465  * @value: boolean value
1466  *
1467  * Set boolean value for specific key
1468  */
1469 int connman_network_set_bool(struct connman_network *network,
1470                                         const char *key, connman_bool_t value)
1471 {
1472         DBG("network %p key %s value %d", network, key, value);
1473
1474         if (g_strcmp0(key, "Roaming") == 0)
1475                 return connman_network_set_roaming(network, value);
1476         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1477                 network->wifi.wps = value;
1478         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1479                 network->wifi.use_wps = value;
1480
1481         return connman_element_set_bool(&network->element, key, value);
1482 }
1483
1484 /**
1485  * connman_network_get_bool:
1486  * @network: network structure
1487  * @key: unique identifier
1488  *
1489  * Get boolean value for specific key
1490  */
1491 connman_bool_t connman_network_get_bool(struct connman_network *network,
1492                                                         const char *key)
1493 {
1494         DBG("network %p key %s", network, key);
1495
1496         if (g_str_equal(key, "Roaming") == TRUE)
1497                 return network->roaming;
1498         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
1499                 return network->wifi.wps;
1500         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
1501                 return network->wifi.use_wps;
1502
1503         return connman_element_get_bool(&network->element, key);
1504 }
1505
1506 /**
1507  * connman_network_set_uint8:
1508  * @network: network structure
1509  * @key: unique identifier
1510  * @value: integer value
1511  *
1512  * Set integer value for specific key
1513  */
1514 int connman_network_set_uint8(struct connman_network *network,
1515                                         const char *key, connman_uint8_t value)
1516 {
1517         DBG("network %p key %s value %d", network, key, value);
1518
1519         if (g_strcmp0(key, "Strength") == 0)
1520                 return connman_network_set_strength(network, value);
1521
1522         return connman_element_set_uint8(&network->element, key, value);
1523 }
1524
1525 /**
1526  * connman_network_get_uint8:
1527  * @network: network structure
1528  * @key: unique identifier
1529  *
1530  * Get integer value for specific key
1531  */
1532 connman_uint8_t connman_network_get_uint8(struct connman_network *network,
1533                                                         const char *key)
1534 {
1535         DBG("network %p key %s", network, key);
1536
1537         if (g_str_equal(key, "Strength") == TRUE)
1538                 return network->strength;
1539
1540         return connman_element_get_uint8(&network->element, key);
1541 }
1542
1543 /**
1544  * connman_network_set_uint16:
1545  * @network: network structure
1546  * @key: unique identifier
1547  * @value: integer value
1548  *
1549  * Set integer value for specific key
1550  */
1551 int connman_network_set_uint16(struct connman_network *network,
1552                                 const char *key, connman_uint16_t value)
1553 {
1554         DBG("network %p key %s value %d", network, key, value);
1555
1556         if (g_str_equal(key, "Frequency") == TRUE)
1557                 network->frequency = value;
1558         else if (g_str_equal(key, "WiFi.Channel") == TRUE)
1559                 network->wifi.channel = value;
1560
1561         return -EINVAL;
1562 }
1563
1564 /**
1565  * connman_network_get_uint16:
1566  * @network: network structure
1567  * @key: unique identifier
1568  *
1569  * Get integer value for specific key
1570  */
1571 connman_uint16_t connman_network_get_uint16(struct connman_network *network,
1572                                                         const char *key)
1573 {
1574         DBG("network %p key %s", network, key);
1575
1576         if (g_str_equal(key, "Frequency") == TRUE)
1577                 return network->frequency;
1578         else if (g_str_equal(key, "WiFi.Channel") == TRUE)
1579                 return network->wifi.channel;
1580
1581         return 0;
1582 }
1583
1584 /**
1585  * connman_network_set_blob:
1586  * @network: network structure
1587  * @key: unique identifier
1588  * @data: blob data
1589  * @size: blob size
1590  *
1591  * Set binary blob value for specific key
1592  */
1593 int connman_network_set_blob(struct connman_network *network,
1594                         const char *key, const void *data, unsigned int size)
1595 {
1596         DBG("network %p key %s size %d", network, key, size);
1597
1598         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1599                 g_free(network->wifi.ssid);
1600                 network->wifi.ssid = g_try_malloc(size);
1601                 if (network->wifi.ssid != NULL) {
1602                         memcpy(network->wifi.ssid, data, size);
1603                         network->wifi.ssid_len = size;
1604                 } else
1605                         network->wifi.ssid_len = 0;
1606         }
1607
1608         return connman_element_set_blob(&network->element, key, data, size);
1609 }
1610
1611 /**
1612  * connman_network_get_blob:
1613  * @network: network structure
1614  * @key: unique identifier
1615  * @size: pointer to blob size
1616  *
1617  * Get binary blob value for specific key
1618  */
1619 const void *connman_network_get_blob(struct connman_network *network,
1620                                         const char *key, unsigned int *size)
1621 {
1622         DBG("network %p key %s", network, key);
1623
1624         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1625                 if (size != NULL)
1626                         *size = network->wifi.ssid_len;
1627                 return network->wifi.ssid;
1628         }
1629
1630         return connman_element_get_blob(&network->element, key, size);
1631 }
1632
1633 void __connman_network_set_device(struct connman_network *network,
1634                                         struct connman_device *device)
1635 {
1636         network->device = device;
1637 }
1638
1639 /**
1640  * connman_network_get_device:
1641  * @network: network structure
1642  *
1643  * Get parent device of network
1644  */
1645 struct connman_device *connman_network_get_device(struct connman_network *network)
1646 {
1647         return network->device;
1648 }
1649
1650 /**
1651  * connman_network_get_data:
1652  * @network: network structure
1653  *
1654  * Get private network data pointer
1655  */
1656 void *connman_network_get_data(struct connman_network *network)
1657 {
1658         return network->driver_data;
1659 }
1660
1661 /**
1662  * connman_network_set_data:
1663  * @network: network structure
1664  * @data: data pointer
1665  *
1666  * Set private network data pointer
1667  */
1668 void connman_network_set_data(struct connman_network *network, void *data)
1669 {
1670         network->driver_data = data;
1671 }
1672
1673 void connman_network_update(struct connman_network *network)
1674 {
1675         switch (network->type) {
1676         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1677         case CONNMAN_NETWORK_TYPE_VENDOR:
1678                 return;
1679         case CONNMAN_NETWORK_TYPE_ETHERNET:
1680         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1681         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1682         case CONNMAN_NETWORK_TYPE_CELLULAR:
1683         case CONNMAN_NETWORK_TYPE_WIFI:
1684         case CONNMAN_NETWORK_TYPE_WIMAX:
1685                 break;
1686         }
1687
1688         if (network->group != NULL)
1689                 __connman_service_update_from_network(network);
1690
1691         return;
1692 }
1693
1694 static gboolean match_driver(struct connman_network *network,
1695                                         struct connman_network_driver *driver)
1696 {
1697         if (network->type == driver->type ||
1698                         driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
1699                 return TRUE;
1700
1701         return FALSE;
1702 }
1703
1704 static int network_probe(struct connman_element *element)
1705 {
1706         struct connman_network *network = element->network;
1707         GSList *list;
1708
1709         DBG("element %p name %s", element, element->name);
1710
1711         if (network == NULL)
1712                 return -ENODEV;
1713
1714         for (list = driver_list; list; list = list->next) {
1715                 struct connman_network_driver *driver = list->data;
1716
1717                 if (match_driver(network, driver) == FALSE)
1718                         continue;
1719
1720                 DBG("driver %p name %s", driver, driver->name);
1721
1722                 if (driver->probe(network) == 0) {
1723                         network->driver = driver;
1724                         break;
1725                 }
1726         }
1727
1728         if (network->driver == NULL)
1729                 return -ENODEV;
1730
1731         switch (network->type) {
1732         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1733         case CONNMAN_NETWORK_TYPE_VENDOR:
1734                 break;
1735         case CONNMAN_NETWORK_TYPE_ETHERNET:
1736         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1737         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1738         case CONNMAN_NETWORK_TYPE_CELLULAR:
1739         case CONNMAN_NETWORK_TYPE_WIFI:
1740         case CONNMAN_NETWORK_TYPE_WIMAX:
1741                 if (network->group != NULL &&
1742                          __connman_service_create_from_network(network) == NULL)
1743                                 return -EINVAL;
1744         }
1745
1746         return 0;
1747 }
1748
1749 static void network_remove(struct connman_element *element)
1750 {
1751         struct connman_network *network = element->network;
1752
1753         DBG("element %p name %s", element, element->name);
1754
1755         if (network == NULL)
1756                 return;
1757
1758         if (network->driver == NULL)
1759                 return;
1760
1761         switch (network->type) {
1762         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1763         case CONNMAN_NETWORK_TYPE_VENDOR:
1764                 break;
1765         case CONNMAN_NETWORK_TYPE_ETHERNET:
1766         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1767         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1768         case CONNMAN_NETWORK_TYPE_CELLULAR:
1769         case CONNMAN_NETWORK_TYPE_WIFI:
1770         case CONNMAN_NETWORK_TYPE_WIMAX:
1771                 if (network->group != NULL) {
1772                         __connman_service_remove_from_network(network);
1773
1774                         g_free(network->group);
1775                         network->group = NULL;
1776                 }
1777                 break;
1778         }
1779
1780         if (network->driver->remove)
1781                 network->driver->remove(network);
1782 }
1783
1784 static void network_change(struct connman_element *element)
1785 {
1786         struct connman_network *network = element->network;
1787
1788         DBG("element %p name %s", element, element->name);
1789
1790         if (element->state != CONNMAN_ELEMENT_STATE_ERROR)
1791                 return;
1792
1793         if (network->connected == FALSE)
1794                 return;
1795
1796         connman_element_unregister_children(element);
1797
1798         connman_device_set_disconnected(network->device, TRUE);
1799
1800         if (network->driver && network->driver->disconnect) {
1801                 network->driver->disconnect(network);
1802                 return;
1803         }
1804
1805         network->connected = FALSE;
1806 }
1807
1808 static struct connman_driver network_driver = {
1809         .name           = "network",
1810         .type           = CONNMAN_ELEMENT_TYPE_NETWORK,
1811         .priority       = CONNMAN_DRIVER_PRIORITY_LOW,
1812         .probe          = network_probe,
1813         .remove         = network_remove,
1814         .change         = network_change,
1815 };
1816
1817 int __connman_network_init(void)
1818 {
1819         DBG("");
1820
1821         return connman_driver_register(&network_driver);
1822 }
1823
1824 void __connman_network_cleanup(void)
1825 {
1826         DBG("");
1827
1828         connman_driver_unregister(&network_driver);
1829 }