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