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