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