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