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