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