network: Replace connman_uint16_t with uint16_t
[platform/upstream/connman.git] / src / network.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2012  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 /*
32  * How many times to send RS with the purpose of
33  * refreshing RDNSS entries before they actually expire.
34  * With a value of 1, one RS will be sent, with no retries.
35  */
36 #define RS_REFRESH_COUNT        1
37
38 /*
39  * Value in seconds to wait for RA after RS was sent.
40  * After this time elapsed, we can send another RS.
41  */
42 #define RS_REFRESH_TIMEOUT      3
43
44 static GSList *network_list = NULL;
45 static GSList *driver_list = NULL;
46
47 struct connman_network {
48         int refcount;
49         enum connman_network_type type;
50         connman_bool_t available;
51         connman_bool_t connected;
52         connman_bool_t roaming;
53         uint8_t strength;
54         uint16_t frequency;
55         char *identifier;
56         char *name;
57         char *node;
58         char *group;
59         char *path;
60         int index;
61         int router_solicit_count;
62         int router_solicit_refresh_count;
63
64         struct connman_network_driver *driver;
65         void *driver_data;
66
67         connman_bool_t connecting;
68         connman_bool_t associating;
69
70         struct connman_device *device;
71
72         struct {
73                 void *ssid;
74                 int ssid_len;
75                 char *mode;
76                 unsigned short channel;
77                 char *security;
78                 char *passphrase;
79                 char *agent_passphrase;
80                 char *eap;
81                 char *identity;
82                 char *agent_identity;
83                 char *ca_cert_path;
84                 char *client_cert_path;
85                 char *private_key_path;
86                 char *private_key_passphrase;
87                 char *phase2_auth;
88                 connman_bool_t wps;
89                 connman_bool_t use_wps;
90                 char *pin_wps;
91         } wifi;
92
93 };
94
95 static const char *type2string(enum connman_network_type type)
96 {
97         switch (type) {
98         case CONNMAN_NETWORK_TYPE_UNKNOWN:
99         case CONNMAN_NETWORK_TYPE_VENDOR:
100                 break;
101         case CONNMAN_NETWORK_TYPE_ETHERNET:
102                 return "ethernet";
103         case CONNMAN_NETWORK_TYPE_WIFI:
104                 return "wifi";
105         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
106         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
107                 return "bluetooth";
108         case CONNMAN_NETWORK_TYPE_CELLULAR:
109                 return "cellular";
110         }
111
112         return NULL;
113 }
114
115 static gboolean match_driver(struct connman_network *network,
116                                         struct connman_network_driver *driver)
117 {
118         if (network->type == driver->type ||
119                         driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
120                 return TRUE;
121
122         return FALSE;
123 }
124
125 static void set_configuration(struct connman_network *network,
126                         enum connman_ipconfig_type type)
127 {
128         struct connman_service *service;
129
130         DBG("network %p", network);
131
132         if (network->device == NULL)
133                 return;
134
135         __connman_device_set_network(network->device, network);
136
137         connman_device_set_disconnected(network->device, FALSE);
138
139         service = connman_service_lookup_from_network(network);
140         __connman_service_ipconfig_indicate_state(service,
141                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
142                                         type);
143 }
144
145 static void dhcp_success(struct connman_network *network)
146 {
147         struct connman_service *service;
148         struct connman_ipconfig *ipconfig_ipv4;
149         int err;
150
151         service = connman_service_lookup_from_network(network);
152         if (service == NULL)
153                 goto err;
154
155         connman_network_set_associating(network, FALSE);
156
157         network->connecting = FALSE;
158
159         ipconfig_ipv4 = __connman_service_get_ip4config(service);
160         err = __connman_ipconfig_address_add(ipconfig_ipv4);
161         if (err < 0)
162                 goto err;
163
164         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
165         if (err < 0)
166                 goto err;
167
168         return;
169
170 err:
171         connman_network_set_error(network,
172                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
173 }
174
175 static void dhcp_failure(struct connman_network *network)
176 {
177         struct connman_service *service;
178
179         service = connman_service_lookup_from_network(network);
180         if (service == NULL)
181                 return;
182
183         __connman_service_ipconfig_indicate_state(service,
184                                         CONNMAN_SERVICE_STATE_IDLE,
185                                         CONNMAN_IPCONFIG_TYPE_IPV4);
186 }
187
188 static void dhcp_callback(struct connman_network *network,
189                         connman_bool_t success)
190 {
191         DBG("success %d", success);
192
193         if (success == TRUE)
194                 dhcp_success(network);
195         else
196                 dhcp_failure(network);
197 }
198
199 static int set_connected_fixed(struct connman_network *network)
200 {
201         struct connman_service *service;
202         struct connman_ipconfig *ipconfig_ipv4;
203         int err;
204
205         DBG("");
206
207         service = connman_service_lookup_from_network(network);
208
209         ipconfig_ipv4 = __connman_service_get_ip4config(service);
210
211         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
212
213         network->connecting = FALSE;
214
215         connman_network_set_associating(network, FALSE);
216
217         err = __connman_ipconfig_address_add(ipconfig_ipv4);
218         if (err < 0)
219                 goto err;
220
221         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
222         if (err < 0)
223                 goto err;
224
225         return 0;
226
227 err:
228         connman_network_set_error(network,
229                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
230
231         return err;
232 }
233
234 static void set_connected_manual(struct connman_network *network)
235 {
236         struct connman_service *service;
237         struct connman_ipconfig *ipconfig;
238         int err;
239
240         DBG("network %p", network);
241
242         service = connman_service_lookup_from_network(network);
243
244         ipconfig = __connman_service_get_ip4config(service);
245
246         if (__connman_ipconfig_get_local(ipconfig) == NULL)
247                 __connman_service_read_ip4config(service);
248
249         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
250
251         err = __connman_ipconfig_address_add(ipconfig);
252         if (err < 0)
253                 goto err;
254
255         err = __connman_ipconfig_gateway_add(ipconfig);
256         if (err < 0)
257                 goto err;
258
259         network->connecting = FALSE;
260
261         connman_network_set_associating(network, FALSE);
262
263         return;
264
265 err:
266         connman_network_set_error(network,
267                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
268         return;
269 }
270
271 static int set_connected_dhcp(struct connman_network *network)
272 {
273         int err;
274
275         DBG("network %p", network);
276
277         set_configuration(network, CONNMAN_IPCONFIG_TYPE_IPV4);
278
279         err = __connman_dhcp_start(network, dhcp_callback);
280         if (err < 0) {
281                 connman_error("Can not request DHCP lease");
282                 return err;
283         }
284
285         return 0;
286 }
287
288 static int manual_ipv6_set(struct connman_network *network,
289                                 struct connman_ipconfig *ipconfig_ipv6)
290 {
291         struct connman_service *service;
292         int err;
293
294         DBG("network %p ipv6 %p", network, ipconfig_ipv6);
295
296         service = connman_service_lookup_from_network(network);
297         if (service == NULL)
298                 return -EINVAL;
299
300         if (__connman_ipconfig_get_local(ipconfig_ipv6) == NULL)
301                 __connman_service_read_ip6config(service);
302
303         __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
304
305         err = __connman_ipconfig_address_add(ipconfig_ipv6);
306         if (err < 0) {
307                 connman_network_set_error(network,
308                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
309                 return err;
310         }
311
312         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
313         if (err < 0)
314                 return err;
315
316         __connman_connection_gateway_activate(service,
317                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
318
319         __connman_device_set_network(network->device, network);
320
321         connman_device_set_disconnected(network->device, FALSE);
322
323         network->connecting = FALSE;
324
325         return 0;
326 }
327
328 static void stop_dhcpv6(struct connman_network *network)
329 {
330         __connman_dhcpv6_stop(network);
331 }
332
333 static void dhcpv6_release_callback(struct connman_network *network,
334                                 connman_bool_t success)
335 {
336         DBG("success %d", success);
337
338         stop_dhcpv6(network);
339 }
340
341 static void release_dhcpv6(struct connman_network *network)
342 {
343         __connman_dhcpv6_start_release(network, dhcpv6_release_callback);
344         stop_dhcpv6(network);
345 }
346
347 static void dhcpv6_info_callback(struct connman_network *network,
348                                 connman_bool_t success)
349 {
350         DBG("success %d", success);
351
352         stop_dhcpv6(network);
353 }
354
355 static gboolean dhcpv6_set_addresses(struct connman_network *network)
356 {
357         struct connman_service *service;
358         struct connman_ipconfig *ipconfig_ipv6;
359         int err = -EINVAL;
360
361         service = connman_service_lookup_from_network(network);
362         if (service == NULL)
363                 goto err;
364
365         connman_network_set_associating(network, FALSE);
366
367         network->connecting = FALSE;
368
369         ipconfig_ipv6 = __connman_service_get_ip6config(service);
370         err = __connman_ipconfig_address_add(ipconfig_ipv6);
371         if (err < 0)
372                 goto err;
373
374         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
375         if (err < 0)
376                 goto err;
377
378         return 0;
379
380 err:
381         connman_network_set_error(network,
382                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
383         return err;
384 }
385
386 static void autoconf_ipv6_set(struct connman_network *network);
387 static void dhcpv6_callback(struct connman_network *network,
388                         connman_bool_t success);
389
390 /*
391  * Have a separate callback for renew so that we do not do autoconf
392  * in wrong phase as the dhcpv6_callback() is also called when doing
393  * DHCPv6 solicitation.
394  */
395 static void dhcpv6_renew_callback(struct connman_network *network,
396                                         connman_bool_t success)
397 {
398         if (success == TRUE)
399                 dhcpv6_callback(network, success);
400         else {
401                 stop_dhcpv6(network);
402
403                 /* restart and do solicit again. */
404                 autoconf_ipv6_set(network);
405         }
406 }
407
408 static void dhcpv6_callback(struct connman_network *network,
409                                         connman_bool_t success)
410 {
411         DBG("success %d", success);
412
413         /* Start the renew process if necessary */
414         if (success == TRUE) {
415
416                 if (dhcpv6_set_addresses(network) < 0) {
417                         stop_dhcpv6(network);
418                         return;
419                 }
420
421                 if (__connman_dhcpv6_start_renew(network,
422                                         dhcpv6_renew_callback) == -ETIMEDOUT)
423                         dhcpv6_renew_callback(network, FALSE);
424         } else
425                 stop_dhcpv6(network);
426 }
427
428 static void check_dhcpv6(struct nd_router_advert *reply,
429                         unsigned int length, void *user_data)
430 {
431         struct connman_network *network = user_data;
432         GSList *prefixes;
433
434         DBG("reply %p", reply);
435
436         if (reply == NULL) {
437                 /*
438                  * Router solicitation message seem to get lost easily so
439                  * try to send it again.
440                  */
441                 if (network->router_solicit_count > 0) {
442                         DBG("re-send router solicitation %d",
443                                                 network->router_solicit_count);
444                         network->router_solicit_count--;
445                         __connman_inet_ipv6_send_rs(network->index, 1,
446                                                 check_dhcpv6, network);
447                         return;
448                 }
449                 connman_network_unref(network);
450                 return;
451         }
452
453         network->router_solicit_count = 0;
454
455         /*
456          * If we were disconnected while waiting router advertisement,
457          * we just quit and do not start DHCPv6
458          */
459         if (network->connected == FALSE) {
460                 connman_network_unref(network);
461                 return;
462         }
463
464         prefixes = __connman_inet_ipv6_get_prefixes(reply, length);
465
466         /*
467          * We do stateful/stateless DHCPv6 if router advertisement says so.
468          */
469         if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
470                 __connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
471         else if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
472                 __connman_dhcpv6_start_info(network, dhcpv6_info_callback);
473
474         connman_network_unref(network);
475 }
476
477 static void receive_refresh_rs_reply(struct nd_router_advert *reply,
478                 unsigned int length, void *user_data)
479 {
480         struct connman_network *network = user_data;
481
482         DBG("reply %p", reply);
483
484         if (reply == NULL) {
485                 /*
486                  * Router solicitation message seem to get lost easily so
487                  * try to send it again.
488                  */
489                 if (network->router_solicit_refresh_count > 1) {
490                         network->router_solicit_refresh_count--;
491                         DBG("re-send router solicitation %d",
492                                         network->router_solicit_refresh_count);
493                         __connman_inet_ipv6_send_rs(network->index,
494                                         RS_REFRESH_TIMEOUT,
495                                         receive_refresh_rs_reply,
496                                         network);
497                         return;
498                 }
499         }
500
501         /* RS refresh not in progress anymore */
502         network->router_solicit_refresh_count = 0;
503
504         connman_network_unref(network);
505         return;
506 }
507
508 int __connman_refresh_rs_ipv6(struct connman_network *network, int index)
509 {
510         int ret = 0;
511
512         DBG("network %p index %d", network, index);
513
514         /* Send only one RS for all RDNSS entries which are about to expire */
515         if (network->router_solicit_refresh_count > 0) {
516                 DBG("RS refresh already started");
517                 return 0;
518         }
519
520         network->router_solicit_refresh_count = RS_REFRESH_COUNT;
521
522         connman_network_ref(network);
523
524         ret = __connman_inet_ipv6_send_rs(index, RS_REFRESH_TIMEOUT,
525                         receive_refresh_rs_reply, network);
526         return ret;
527 }
528
529 static void autoconf_ipv6_set(struct connman_network *network)
530 {
531         struct connman_service *service;
532         struct connman_ipconfig *ipconfig;
533         int index;
534
535         DBG("network %p", network);
536
537         if (network->router_solicit_count > 0) {
538                 /*
539                  * The autoconfiguration is already pending and we have sent
540                  * router solicitation messages and are now waiting answers.
541                  * There is no need to continue any further.
542                  */
543                 DBG("autoconfiguration already started");
544                 return;
545         }
546
547         __connman_device_set_network(network->device, network);
548
549         connman_device_set_disconnected(network->device, FALSE);
550
551         network->connecting = FALSE;
552
553         service = connman_service_lookup_from_network(network);
554         if (service == NULL)
555                 return;
556
557         ipconfig = __connman_service_get_ip6config(service);
558         if (ipconfig == NULL)
559                 return;
560
561         index = __connman_ipconfig_get_index(ipconfig);
562
563         connman_network_ref(network);
564
565         /* Try to get stateless DHCPv6 information, RFC 3736 */
566         network->router_solicit_count = 3;
567         __connman_inet_ipv6_send_rs(index, 1, check_dhcpv6, network);
568 }
569
570 static void set_connected(struct connman_network *network)
571 {
572         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
573         enum connman_ipconfig_method ipv4_method, ipv6_method;
574         struct connman_service *service;
575         int ret;
576
577         if (network->connected == TRUE)
578                 return;
579
580         network->connected = TRUE;
581
582         service = connman_service_lookup_from_network(network);
583
584         ipconfig_ipv4 = __connman_service_get_ip4config(service);
585         ipconfig_ipv6 = __connman_service_get_ip6config(service);
586
587         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
588                 ipconfig_ipv6);
589
590         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
591         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
592
593         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
594
595         switch (ipv6_method) {
596         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
597         case CONNMAN_IPCONFIG_METHOD_OFF:
598                 break;
599         case CONNMAN_IPCONFIG_METHOD_DHCP:
600         case CONNMAN_IPCONFIG_METHOD_AUTO:
601                 autoconf_ipv6_set(network);
602                 break;
603         case CONNMAN_IPCONFIG_METHOD_FIXED:
604         case CONNMAN_IPCONFIG_METHOD_MANUAL:
605                 ret = manual_ipv6_set(network, ipconfig_ipv6);
606                 if (ret != 0) {
607                         connman_network_set_error(network,
608                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
609                         return;
610                 }
611                 break;
612         }
613
614         switch (ipv4_method) {
615         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
616         case CONNMAN_IPCONFIG_METHOD_OFF:
617         case CONNMAN_IPCONFIG_METHOD_AUTO:
618                 return;
619         case CONNMAN_IPCONFIG_METHOD_FIXED:
620                 if (set_connected_fixed(network) < 0) {
621                         connman_network_set_error(network,
622                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
623                         return;
624                 }
625                 return;
626         case CONNMAN_IPCONFIG_METHOD_MANUAL:
627                 set_connected_manual(network);
628                 return;
629         case CONNMAN_IPCONFIG_METHOD_DHCP:
630                 if (set_connected_dhcp(network) < 0) {
631                         connman_network_set_error(network,
632                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
633                         return;
634                 }
635         }
636
637         network->connecting = FALSE;
638
639         connman_network_set_associating(network, FALSE);
640 }
641
642 static void set_disconnected(struct connman_network *network)
643 {
644         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
645         enum connman_ipconfig_method ipv4_method, ipv6_method;
646         enum connman_service_state state;
647         struct connman_service *service;
648
649         if (network->connected == FALSE)
650                 return;
651
652         network->connected = FALSE;
653
654         service = connman_service_lookup_from_network(network);
655
656         ipconfig_ipv4 = __connman_service_get_ip4config(service);
657         ipconfig_ipv6 = __connman_service_get_ip6config(service);
658
659         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
660                 ipconfig_ipv6);
661
662         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
663         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
664
665         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
666
667         /*
668          * Resetting solicit count here will prevent the RS resend loop
669          * from sending packets in check_dhcpv6()
670          */
671         network->router_solicit_count = 0;
672
673         __connman_device_set_network(network->device, NULL);
674
675         switch (ipv6_method) {
676         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
677         case CONNMAN_IPCONFIG_METHOD_OFF:
678         case CONNMAN_IPCONFIG_METHOD_FIXED:
679         case CONNMAN_IPCONFIG_METHOD_MANUAL:
680                 break;
681         case CONNMAN_IPCONFIG_METHOD_DHCP:
682         case CONNMAN_IPCONFIG_METHOD_AUTO:
683                 release_dhcpv6(network);
684                 break;
685         }
686
687         switch (ipv4_method) {
688         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
689         case CONNMAN_IPCONFIG_METHOD_OFF:
690         case CONNMAN_IPCONFIG_METHOD_AUTO:
691         case CONNMAN_IPCONFIG_METHOD_FIXED:
692         case CONNMAN_IPCONFIG_METHOD_MANUAL:
693                 break;
694         case CONNMAN_IPCONFIG_METHOD_DHCP:
695                 __connman_dhcp_stop(network);
696                 break;
697         }
698
699         /*
700          * We only set the disconnect state if we were not in idle
701          * or in failure. It does not make sense to go to disconnect
702          * state if we were not connected.
703          */
704         state = __connman_service_ipconfig_get_state(service,
705                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
706         if (state != CONNMAN_SERVICE_STATE_IDLE &&
707                         state != CONNMAN_SERVICE_STATE_FAILURE)
708                 __connman_service_ipconfig_indicate_state(service,
709                                         CONNMAN_SERVICE_STATE_DISCONNECT,
710                                         CONNMAN_IPCONFIG_TYPE_IPV4);
711
712         state = __connman_service_ipconfig_get_state(service,
713                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
714         if (state != CONNMAN_SERVICE_STATE_IDLE &&
715                                 state != CONNMAN_SERVICE_STATE_FAILURE)
716                 __connman_service_ipconfig_indicate_state(service,
717                                         CONNMAN_SERVICE_STATE_DISCONNECT,
718                                         CONNMAN_IPCONFIG_TYPE_IPV6);
719
720         __connman_connection_gateway_remove(service,
721                                         CONNMAN_IPCONFIG_TYPE_ALL);
722
723         __connman_ipconfig_address_unset(ipconfig_ipv4);
724         __connman_ipconfig_address_unset(ipconfig_ipv6);
725
726         /*
727          * Special handling for IPv6 autoconfigured address.
728          * The simplest way to remove autoconfigured routes is to
729          * disable IPv6 temporarily so that kernel will do the cleanup
730          * automagically.
731          */
732         if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
733                 __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
734                 __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
735         }
736
737         __connman_service_ipconfig_indicate_state(service,
738                                                 CONNMAN_SERVICE_STATE_IDLE,
739                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
740
741         __connman_service_ipconfig_indicate_state(service,
742                                                 CONNMAN_SERVICE_STATE_IDLE,
743                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
744
745         network->connecting = FALSE;
746
747         connman_network_set_associating(network, FALSE);
748 }
749
750
751
752 static int network_probe(struct connman_network *network)
753 {
754         GSList *list;
755         struct connman_network_driver *driver = NULL;
756
757         DBG("network %p name %s", network, network->name);
758
759         if (network->driver != NULL)
760                 return -EALREADY;
761
762         for (list = driver_list; list; list = list->next) {
763                 driver = list->data;
764
765                 if (match_driver(network, driver) == FALSE) {
766                         driver = NULL;
767                         continue;
768                 }
769
770                 DBG("driver %p name %s", driver, driver->name);
771
772                 if (driver->probe(network) == 0)
773                         break;
774
775                 driver = NULL;
776         }
777
778         if (driver == NULL)
779                 return -ENODEV;
780
781         if (network->group == NULL)
782                 return -EINVAL;
783
784         switch (network->type) {
785         case CONNMAN_NETWORK_TYPE_UNKNOWN:
786         case CONNMAN_NETWORK_TYPE_VENDOR:
787                 return 0;
788         case CONNMAN_NETWORK_TYPE_ETHERNET:
789         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
790         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
791         case CONNMAN_NETWORK_TYPE_CELLULAR:
792         case CONNMAN_NETWORK_TYPE_WIFI:
793                 network->driver = driver;
794                 if (__connman_service_create_from_network(network) == NULL) {
795                         network->driver = NULL;
796                         return -EINVAL;
797                 }
798         }
799
800         return 0;
801 }
802
803 static void network_remove(struct connman_network *network)
804 {
805         DBG("network %p name %s", network, network->name);
806
807         if (network->driver == NULL)
808                 return;
809
810         if (network->connected == TRUE)
811                 set_disconnected(network);
812
813         switch (network->type) {
814         case CONNMAN_NETWORK_TYPE_UNKNOWN:
815         case CONNMAN_NETWORK_TYPE_VENDOR:
816                 break;
817         case CONNMAN_NETWORK_TYPE_ETHERNET:
818         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
819         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
820         case CONNMAN_NETWORK_TYPE_CELLULAR:
821         case CONNMAN_NETWORK_TYPE_WIFI:
822                 if (network->group != NULL) {
823                         __connman_service_remove_from_network(network);
824
825                         g_free(network->group);
826                         network->group = NULL;
827                 }
828                 break;
829         }
830
831         if (network->driver->remove)
832                 network->driver->remove(network);
833
834         network->driver = NULL;
835 }
836
837 static void network_change(struct connman_network *network)
838 {
839         DBG("network %p name %s", network, network->name);
840
841         if (network->connected == FALSE)
842                 return;
843
844         connman_device_set_disconnected(network->device, TRUE);
845
846         if (network->driver && network->driver->disconnect) {
847                 network->driver->disconnect(network);
848                 return;
849         }
850
851         network->connected = FALSE;
852 }
853
854 static void probe_driver(struct connman_network_driver *driver)
855 {
856         GSList *list;
857
858         DBG("driver %p name %s", driver, driver->name);
859
860         for (list = network_list; list != NULL; list = list->next) {
861                 struct connman_network *network = list->data;
862
863                 if (network->driver != NULL)
864                         continue;
865
866                 if (driver->type != network->type)
867                         continue;
868
869                 if (driver->probe(network) < 0)
870                         continue;
871
872                 network->driver = driver;
873         }
874 }
875
876 static void remove_driver(struct connman_network_driver *driver)
877 {
878         GSList *list;
879
880         DBG("driver %p name %s", driver, driver->name);
881
882         for (list = network_list; list != NULL; list = list->next) {
883                 struct connman_network *network = list->data;
884
885                 if (network->driver == driver)
886                         network_remove(network);
887         }
888 }
889
890 static gint compare_priority(gconstpointer a, gconstpointer b)
891 {
892         const struct connman_network_driver *driver1 = a;
893         const struct connman_network_driver *driver2 = b;
894
895         return driver2->priority - driver1->priority;
896 }
897
898 /**
899  * connman_network_driver_register:
900  * @driver: network driver definition
901  *
902  * Register a new network driver
903  *
904  * Returns: %0 on success
905  */
906 int connman_network_driver_register(struct connman_network_driver *driver)
907 {
908         DBG("driver %p name %s", driver, driver->name);
909
910         driver_list = g_slist_insert_sorted(driver_list, driver,
911                                                         compare_priority);
912
913         probe_driver(driver);
914
915         return 0;
916 }
917
918 /**
919  * connman_network_driver_unregister:
920  * @driver: network driver definition
921  *
922  * Remove a previously registered network driver
923  */
924 void connman_network_driver_unregister(struct connman_network_driver *driver)
925 {
926         DBG("driver %p name %s", driver, driver->name);
927
928         driver_list = g_slist_remove(driver_list, driver);
929
930         remove_driver(driver);
931 }
932
933 static void network_destruct(struct connman_network *network)
934 {
935         DBG("network %p name %s", network, network->name);
936
937         g_free(network->wifi.ssid);
938         g_free(network->wifi.mode);
939         g_free(network->wifi.security);
940         g_free(network->wifi.passphrase);
941         g_free(network->wifi.agent_passphrase);
942         g_free(network->wifi.eap);
943         g_free(network->wifi.identity);
944         g_free(network->wifi.agent_identity);
945         g_free(network->wifi.ca_cert_path);
946         g_free(network->wifi.client_cert_path);
947         g_free(network->wifi.private_key_path);
948         g_free(network->wifi.private_key_passphrase);
949         g_free(network->wifi.phase2_auth);
950         g_free(network->wifi.pin_wps);
951
952         g_free(network->path);
953         g_free(network->group);
954         g_free(network->node);
955         g_free(network->name);
956         g_free(network->identifier);
957
958         network->device = NULL;
959
960         g_free(network);
961 }
962
963 /**
964  * connman_network_create:
965  * @identifier: network identifier (for example an unqiue name)
966  *
967  * Allocate a new network and assign the #identifier to it.
968  *
969  * Returns: a newly-allocated #connman_network structure
970  */
971 struct connman_network *connman_network_create(const char *identifier,
972                                                 enum connman_network_type type)
973 {
974         struct connman_network *network;
975         char *ident;
976
977         DBG("identifier %s type %d", identifier, type);
978
979         network = g_try_new0(struct connman_network, 1);
980         if (network == NULL)
981                 return NULL;
982
983         DBG("network %p", network);
984
985         network->refcount = 1;
986
987         ident = g_strdup(identifier);
988
989         if (ident == NULL) {
990                 g_free(network);
991                 return NULL;
992         }
993
994         network->type       = type;
995         network->identifier = ident;
996
997         network_list = g_slist_prepend(network_list, network);
998
999         return network;
1000 }
1001
1002 /**
1003  * connman_network_ref:
1004  * @network: network structure
1005  *
1006  * Increase reference counter of  network
1007  */
1008 struct connman_network *
1009 connman_network_ref_debug(struct connman_network *network,
1010                         const char *file, int line, const char *caller)
1011 {
1012         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1013                 network->refcount + 1, file, line, caller);
1014
1015         __sync_fetch_and_add(&network->refcount, 1);
1016
1017         return network;
1018 }
1019
1020 /**
1021  * connman_network_unref:
1022  * @network: network structure
1023  *
1024  * Decrease reference counter of network
1025  */
1026 void connman_network_unref_debug(struct connman_network *network,
1027                                 const char *file, int line, const char *caller)
1028 {
1029         DBG("%p name %s ref %d by %s:%d:%s()", network, network->name,
1030                 network->refcount - 1, file, line, caller);
1031
1032         if (__sync_fetch_and_sub(&network->refcount, 1) != 1)
1033                 return;
1034
1035         network_list = g_slist_remove(network_list, network);
1036
1037         network_destruct(network);
1038 }
1039
1040 const char *__connman_network_get_type(struct connman_network *network)
1041 {
1042         return type2string(network->type);
1043 }
1044
1045 /**
1046  * connman_network_get_type:
1047  * @network: network structure
1048  *
1049  * Get type of network
1050  */
1051 enum connman_network_type connman_network_get_type(struct connman_network *network)
1052 {
1053         return network->type;
1054 }
1055
1056 /**
1057  * connman_network_get_identifier:
1058  * @network: network structure
1059  *
1060  * Get identifier of network
1061  */
1062 const char *connman_network_get_identifier(struct connman_network *network)
1063 {
1064         return network->identifier;
1065 }
1066
1067 /**
1068  * connman_network_set_index:
1069  * @network: network structure
1070  * @index: index number
1071  *
1072  * Set index number of network
1073  */
1074 void connman_network_set_index(struct connman_network *network, int index)
1075 {
1076         struct connman_service *service;
1077         struct connman_ipconfig *ipconfig;
1078
1079         service = connman_service_lookup_from_network(network);
1080         if (service == NULL)
1081                 goto done;
1082
1083         ipconfig = __connman_service_get_ip4config(service);
1084         if (ipconfig == NULL)
1085                 goto done;
1086
1087         /* If index changed, the index of ipconfig must be reset. */
1088         __connman_ipconfig_set_index(ipconfig, index);
1089
1090         DBG("index %d service %p ip4config %p", network->index,
1091                 service, ipconfig);
1092 done:
1093         network->index = index;
1094 }
1095
1096 /**
1097  * connman_network_get_index:
1098  * @network: network structure
1099  *
1100  * Get index number of network
1101  */
1102 int connman_network_get_index(struct connman_network *network)
1103 {
1104         return network->index;
1105 }
1106
1107 /**
1108  * connman_network_set_group:
1109  * @network: network structure
1110  * @group: group name
1111  *
1112  * Set group name for automatic clustering
1113  */
1114 void connman_network_set_group(struct connman_network *network,
1115                                                         const char *group)
1116 {
1117         switch (network->type) {
1118         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1119         case CONNMAN_NETWORK_TYPE_VENDOR:
1120                 return;
1121         case CONNMAN_NETWORK_TYPE_ETHERNET:
1122         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1123         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1124         case CONNMAN_NETWORK_TYPE_CELLULAR:
1125         case CONNMAN_NETWORK_TYPE_WIFI:
1126                 break;
1127         }
1128
1129         if (g_strcmp0(network->group, group) == 0) {
1130                 if (group != NULL)
1131                         __connman_service_update_from_network(network);
1132                 return;
1133         }
1134
1135         if (network->group != NULL) {
1136                 __connman_service_remove_from_network(network);
1137
1138                 g_free(network->group);
1139         }
1140
1141         network->group = g_strdup(group);
1142
1143         if (network->group != NULL)
1144                 network_probe(network);
1145 }
1146
1147 /**
1148  * connman_network_get_group:
1149  * @network: network structure
1150  *
1151  * Get group name for automatic clustering
1152  */
1153 const char *connman_network_get_group(struct connman_network *network)
1154 {
1155         return network->group;
1156 }
1157
1158 const char *__connman_network_get_ident(struct connman_network *network)
1159 {
1160         if (network->device == NULL)
1161                 return NULL;
1162
1163         return connman_device_get_ident(network->device);
1164 }
1165
1166 connman_bool_t __connman_network_get_weakness(struct connman_network *network)
1167 {
1168         switch (network->type) {
1169         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1170         case CONNMAN_NETWORK_TYPE_VENDOR:
1171         case CONNMAN_NETWORK_TYPE_ETHERNET:
1172         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1173         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1174         case CONNMAN_NETWORK_TYPE_CELLULAR:
1175                 break;
1176         case CONNMAN_NETWORK_TYPE_WIFI:
1177                 if (g_strcmp0(network->wifi.mode, "adhoc") == 0)
1178                         return TRUE;
1179                 if (network->strength > 0 && network->strength < 20)
1180                         return TRUE;
1181                 break;
1182         }
1183
1184         return FALSE;
1185 }
1186
1187 connman_bool_t connman_network_get_connecting(struct connman_network *network)
1188 {
1189         return network->connecting;
1190 }
1191
1192 /**
1193  * connman_network_set_available:
1194  * @network: network structure
1195  * @available: availability state
1196  *
1197  * Change availability state of network (in range)
1198  */
1199 int connman_network_set_available(struct connman_network *network,
1200                                                 connman_bool_t available)
1201 {
1202         DBG("network %p available %d", network, available);
1203
1204         if (network->available == available)
1205                 return -EALREADY;
1206
1207         network->available = available;
1208
1209         return 0;
1210 }
1211
1212 /**
1213  * connman_network_get_available:
1214  * @network: network structure
1215  *
1216  * Get network available setting
1217  */
1218 connman_bool_t connman_network_get_available(struct connman_network *network)
1219 {
1220         return network->available;
1221 }
1222
1223 /**
1224  * connman_network_set_associating:
1225  * @network: network structure
1226  * @associating: associating state
1227  *
1228  * Change associating state of network
1229  */
1230 int connman_network_set_associating(struct connman_network *network,
1231                                                 connman_bool_t associating)
1232 {
1233         DBG("network %p associating %d", network, associating);
1234
1235         if (network->associating == associating)
1236                 return -EALREADY;
1237
1238         network->associating = associating;
1239
1240         if (associating == TRUE) {
1241                 struct connman_service *service;
1242
1243                 service = connman_service_lookup_from_network(network);
1244                 __connman_service_ipconfig_indicate_state(service,
1245                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1246                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1247                 __connman_service_ipconfig_indicate_state(service,
1248                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
1249                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1250         }
1251
1252         return 0;
1253 }
1254
1255 static void set_associate_error(struct connman_network *network)
1256 {
1257         struct connman_service *service;
1258
1259         service = connman_service_lookup_from_network(network);
1260
1261         __connman_service_indicate_error(service,
1262                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1263 }
1264
1265 static void set_configure_error(struct connman_network *network)
1266 {
1267         struct connman_service *service;
1268
1269         service = connman_service_lookup_from_network(network);
1270
1271         __connman_service_indicate_error(service,
1272                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1273 }
1274
1275 static void set_invalid_key_error(struct connman_network *network)
1276 {
1277         struct connman_service *service;
1278
1279         service = connman_service_lookup_from_network(network);
1280
1281         __connman_service_indicate_error(service,
1282                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1283 }
1284
1285 static void set_connect_error(struct connman_network *network)
1286 {
1287         struct connman_service *service;
1288
1289         service = connman_service_lookup_from_network(network);
1290
1291         __connman_service_indicate_error(service,
1292                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
1293 }
1294
1295 void connman_network_set_ipv4_method(struct connman_network *network,
1296                                         enum connman_ipconfig_method method)
1297 {
1298         struct connman_service *service;
1299         struct connman_ipconfig *ipconfig;
1300
1301         service = connman_service_lookup_from_network(network);
1302         if (service == NULL)
1303                 return;
1304
1305         ipconfig = __connman_service_get_ip4config(service);
1306         if (ipconfig == NULL)
1307                 return;
1308
1309         __connman_ipconfig_set_method(ipconfig, method);
1310 }
1311
1312 void connman_network_set_ipv6_method(struct connman_network *network,
1313                                         enum connman_ipconfig_method method)
1314 {
1315         struct connman_service *service;
1316         struct connman_ipconfig *ipconfig;
1317
1318         service = connman_service_lookup_from_network(network);
1319         if (service == NULL)
1320                 return;
1321
1322         ipconfig = __connman_service_get_ip6config(service);
1323         if (ipconfig == NULL)
1324                 return;
1325
1326         __connman_ipconfig_set_method(ipconfig, method);
1327 }
1328
1329 void connman_network_set_error(struct connman_network *network,
1330                                         enum connman_network_error error)
1331 {
1332         DBG("network %p error %d", network, error);
1333
1334         network->connecting = FALSE;
1335         network->associating = FALSE;
1336
1337         switch (error) {
1338         case CONNMAN_NETWORK_ERROR_UNKNOWN:
1339                 return;
1340         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
1341                 set_associate_error(network);
1342                 break;
1343         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
1344                 set_configure_error(network);
1345                 break;
1346         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
1347                 set_invalid_key_error(network);
1348                 break;
1349         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
1350                 set_connect_error(network);
1351                 break;
1352         }
1353
1354         network_change(network);
1355 }
1356
1357 void connman_network_clear_error(struct connman_network *network)
1358 {
1359         struct connman_service *service;
1360
1361         DBG("network %p", network);
1362
1363         if (network == NULL)
1364                 return;
1365
1366         if (network->connecting == TRUE || network->associating == TRUE)
1367                 return;
1368
1369         service = connman_service_lookup_from_network(network);
1370         __connman_service_clear_error(service);
1371 }
1372
1373 /**
1374  * connman_network_set_connected:
1375  * @network: network structure
1376  * @connected: connected state
1377  *
1378  * Change connected state of network
1379  */
1380 int connman_network_set_connected(struct connman_network *network,
1381                                                 connman_bool_t connected)
1382 {
1383         DBG("network %p connected %d/%d connecting %d associating %d",
1384                 network, network->connected, connected, network->connecting,
1385                 network->associating);
1386
1387         if ((network->connecting == TRUE || network->associating == TRUE) &&
1388                                                         connected == FALSE) {
1389                 connman_network_set_error(network,
1390                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1391                 if (__connman_network_disconnect(network) == 0)
1392                         return 0;
1393         }
1394
1395         if (network->connected == connected)
1396                 return -EALREADY;
1397
1398         if (connected == FALSE)
1399                 set_disconnected(network);
1400         else
1401                 set_connected(network);
1402
1403         return 0;
1404 }
1405
1406 /**
1407  * connman_network_get_connected:
1408  * @network: network structure
1409  *
1410  * Get network connection status
1411  */
1412 connman_bool_t connman_network_get_connected(struct connman_network *network)
1413 {
1414         return network->connected;
1415 }
1416
1417 /**
1418  * connman_network_get_associating:
1419  * @network: network structure
1420  *
1421  * Get network associating status
1422  */
1423 connman_bool_t connman_network_get_associating(struct connman_network *network)
1424 {
1425         return network->associating;
1426 }
1427
1428 void connman_network_clear_hidden(void *user_data)
1429 {
1430         if (user_data == NULL)
1431                 return;
1432
1433         DBG("user_data %p", user_data);
1434
1435         /*
1436          * Hidden service does not have a connect timeout so
1437          * we do not need to remove it. We can just return
1438          * error to the caller telling that we could not find
1439          * any network that we could connect to.
1440          */
1441         __connman_service_reply_dbus_pending(user_data, EIO, NULL);
1442 }
1443
1444 int connman_network_connect_hidden(struct connman_network *network,
1445                         char *identity, char* passphrase, void *user_data)
1446 {
1447         int err = 0;
1448         struct connman_service *service;
1449
1450         service = connman_service_lookup_from_network(network);
1451
1452         DBG("network %p service %p user_data %p", network, service, user_data);
1453
1454         if (service == NULL) {
1455                 err = -EINVAL;
1456                 goto out;
1457         }
1458
1459         if (identity != NULL)
1460                 __connman_service_set_agent_identity(service, identity);
1461
1462         if (passphrase != NULL)
1463                 err = __connman_service_add_passphrase(service, passphrase);
1464
1465         if (err == -ENOKEY) {
1466                 __connman_service_indicate_error(service,
1467                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
1468                 goto out;
1469         } else {
1470                 __connman_service_set_hidden(service);
1471                 __connman_service_set_userconnect(service, TRUE);
1472                 __connman_service_set_hidden_data(service, user_data);
1473                 return __connman_service_connect(service);
1474         }
1475
1476 out:
1477         __connman_service_return_error(service, -err, user_data);
1478         return err;
1479 }
1480
1481 /**
1482  * __connman_network_connect:
1483  * @network: network structure
1484  *
1485  * Connect network
1486  */
1487 int __connman_network_connect(struct connman_network *network)
1488 {
1489         int err;
1490
1491         DBG("network %p", network);
1492
1493         if (network->connected == TRUE)
1494                 return -EISCONN;
1495
1496         if (network->connecting == TRUE || network->associating == TRUE)
1497                 return -EALREADY;
1498
1499         if (network->driver == NULL)
1500                 return -EUNATCH;
1501
1502         if (network->driver->connect == NULL)
1503                 return -ENOSYS;
1504
1505         if (network->device == NULL)
1506                 return -ENODEV;
1507
1508         network->connecting = TRUE;
1509
1510         __connman_device_disconnect(network->device);
1511
1512         err = network->driver->connect(network);
1513         if (err < 0) {
1514                 if (err == -EINPROGRESS)
1515                         connman_network_set_associating(network, TRUE);
1516                 else {
1517                         network->connecting = FALSE;
1518                 }
1519
1520                 return err;
1521         }
1522
1523         set_connected(network);
1524
1525         return err;
1526 }
1527
1528 /**
1529  * __connman_network_disconnect:
1530  * @network: network structure
1531  *
1532  * Disconnect network
1533  */
1534 int __connman_network_disconnect(struct connman_network *network)
1535 {
1536         int err;
1537
1538         DBG("network %p", network);
1539
1540         if (network->connected == FALSE && network->connecting == FALSE &&
1541                                                 network->associating == FALSE)
1542                 return -ENOTCONN;
1543
1544         if (network->driver == NULL)
1545                 return -EUNATCH;
1546
1547         if (network->driver->disconnect == NULL)
1548                 return -ENOSYS;
1549
1550         network->connecting = FALSE;
1551
1552         err = network->driver->disconnect(network);
1553         if (err == 0)
1554                 set_disconnected(network);
1555
1556         return err;
1557 }
1558
1559 static int manual_ipv4_set(struct connman_network *network,
1560                                 struct connman_ipconfig *ipconfig)
1561 {
1562         struct connman_service *service;
1563         int err;
1564
1565         service = connman_service_lookup_from_network(network);
1566         if (service == NULL)
1567                 return -EINVAL;
1568
1569         err = __connman_ipconfig_address_add(ipconfig);
1570         if (err < 0) {
1571                 connman_network_set_error(network,
1572                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1573                 return err;
1574         }
1575
1576         return __connman_ipconfig_gateway_add(ipconfig);
1577 }
1578
1579 int __connman_network_clear_ipconfig(struct connman_network *network,
1580                                         struct connman_ipconfig *ipconfig)
1581 {
1582         struct connman_service *service;
1583         enum connman_ipconfig_method method;
1584         enum connman_ipconfig_type type;
1585
1586         service = connman_service_lookup_from_network(network);
1587         if (service == NULL)
1588                 return -EINVAL;
1589
1590         method = __connman_ipconfig_get_method(ipconfig);
1591         type = __connman_ipconfig_get_config_type(ipconfig);
1592
1593         switch (method) {
1594         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1595         case CONNMAN_IPCONFIG_METHOD_OFF:
1596         case CONNMAN_IPCONFIG_METHOD_FIXED:
1597                 return -EINVAL;
1598         case CONNMAN_IPCONFIG_METHOD_AUTO:
1599                 release_dhcpv6(network);
1600                 break;
1601         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1602                 __connman_ipconfig_address_remove(ipconfig);
1603                 break;
1604         case CONNMAN_IPCONFIG_METHOD_DHCP:
1605                 __connman_dhcp_stop(network);
1606                 break;
1607         }
1608
1609         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1610                 __connman_service_ipconfig_indicate_state(service,
1611                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1612                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1613         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1614                 __connman_service_ipconfig_indicate_state(service,
1615                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1616                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1617
1618         return 0;
1619 }
1620
1621 int __connman_network_set_ipconfig(struct connman_network *network,
1622                                         struct connman_ipconfig *ipconfig_ipv4,
1623                                         struct connman_ipconfig *ipconfig_ipv6)
1624 {
1625         enum connman_ipconfig_method method;
1626         int ret;
1627
1628         if (network == NULL)
1629                 return -EINVAL;
1630
1631         if (ipconfig_ipv6) {
1632                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1633
1634                 switch (method) {
1635                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1636                 case CONNMAN_IPCONFIG_METHOD_OFF:
1637                         break;
1638                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1639                         autoconf_ipv6_set(network);
1640                         break;
1641                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1642                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1643                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1644                         if (ret != 0) {
1645                                 connman_network_set_error(network,
1646                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1647                                 return ret;
1648                         }
1649                         break;
1650                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1651                         break;
1652                 }
1653         }
1654
1655         if (ipconfig_ipv4) {
1656                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1657
1658                 switch (method) {
1659                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1660                 case CONNMAN_IPCONFIG_METHOD_OFF:
1661                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1662                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1663                         return -EINVAL;
1664                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1665                         return manual_ipv4_set(network, ipconfig_ipv4);
1666                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1667                         return __connman_dhcp_start(network, dhcp_callback);
1668                 }
1669         }
1670
1671         return 0;
1672 }
1673
1674 int connman_network_set_ipaddress(struct connman_network *network,
1675                                         struct connman_ipaddress *ipaddress)
1676 {
1677         struct connman_service *service;
1678         struct connman_ipconfig *ipconfig = NULL;
1679
1680         DBG("network %p", network);
1681
1682         service = connman_service_lookup_from_network(network);
1683         if (service == NULL)
1684                 return -EINVAL;
1685
1686         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1687         if (ipconfig == NULL)
1688                 return -EINVAL;
1689
1690         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1691         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1692         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1693         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1694         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1695
1696         return 0;
1697 }
1698
1699 int connman_network_set_nameservers(struct connman_network *network,
1700                                 const char *nameservers)
1701 {
1702         struct connman_service *service;
1703         char **nameservers_array;
1704         int i;
1705
1706         DBG("network %p nameservers %s", network, nameservers);
1707
1708         service = connman_service_lookup_from_network(network);
1709         if (service == NULL)
1710                 return -EINVAL;
1711
1712         __connman_service_nameserver_clear(service);
1713
1714         if (nameservers == NULL)
1715                 return 0;
1716
1717         nameservers_array = g_strsplit(nameservers, " ", 0);
1718
1719         for (i = 0; nameservers_array[i] != NULL; i++) {
1720                 __connman_service_nameserver_append(service,
1721                                                 nameservers_array[i], FALSE);
1722         }
1723
1724         g_strfreev(nameservers_array);
1725
1726         return 0;
1727 }
1728
1729 int connman_network_set_domain(struct connman_network *network,
1730                                 const char *domain)
1731 {
1732         struct connman_service *service;
1733
1734         DBG("network %p domain %s", network, domain);
1735
1736         service = connman_service_lookup_from_network(network);
1737         if (service == NULL)
1738                 return -EINVAL;
1739
1740         __connman_service_set_domainname(service, domain);
1741
1742         return 0;
1743 }
1744
1745 /**
1746  * connman_network_set_name:
1747  * @network: network structure
1748  * @name: name value
1749  *
1750  * Set display name value for network
1751  */
1752 int connman_network_set_name(struct connman_network *network,
1753                                                         const char *name)
1754 {
1755         DBG("network %p name %s", network, name);
1756
1757         g_free(network->name);
1758         network->name = g_strdup(name);
1759
1760         return 0;
1761 }
1762
1763 /**
1764  * connman_network_set_strength:
1765  * @network: network structure
1766  * @strength: strength value
1767  *
1768  * Set signal strength value for network
1769  */
1770
1771 int connman_network_set_strength(struct connman_network *network,
1772                                                 uint8_t strength)
1773 {
1774         DBG("network %p strengh %d", network, strength);
1775
1776         network->strength = strength;
1777
1778         return 0;
1779 }
1780
1781 uint8_t connman_network_get_strength(struct connman_network *network)
1782 {
1783         return network->strength;
1784 }
1785
1786 int connman_network_set_frequency(struct connman_network *network,
1787                                                 uint16_t frequency)
1788 {
1789         DBG("network %p frequency %d", network, frequency);
1790
1791         network->frequency = frequency;
1792
1793         return 0;
1794 }
1795
1796 uint16_t connman_network_get_frequency(struct connman_network *network)
1797 {
1798         return network->frequency;
1799 }
1800
1801 int connman_network_set_wifi_channel(struct connman_network *network,
1802                                                 uint16_t channel)
1803 {
1804         DBG("network %p wifi channel %d", network, channel);
1805
1806         network->wifi.channel = channel;
1807
1808         return 0;
1809 }
1810
1811 uint16_t connman_network_get_wifi_channel(struct connman_network *network)
1812 {
1813         return network->wifi.channel;
1814 }
1815
1816 /**
1817  * connman_network_set_string:
1818  * @network: network structure
1819  * @key: unique identifier
1820  * @value: string value
1821  *
1822  * Set string value for specific key
1823  */
1824 int connman_network_set_string(struct connman_network *network,
1825                                         const char *key, const char *value)
1826 {
1827         DBG("network %p key %s value %s", network, key, value);
1828
1829         if (g_strcmp0(key, "Name") == 0)
1830                 return connman_network_set_name(network, value);
1831
1832         if (g_str_equal(key, "Path") == TRUE) {
1833                 g_free(network->path);
1834                 network->path = g_strdup(value);
1835         } else if (g_str_equal(key, "Node") == TRUE) {
1836                 g_free(network->node);
1837                 network->node = g_strdup(value);
1838         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1839                 g_free(network->wifi.mode);
1840                 network->wifi.mode = g_strdup(value);
1841         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1842                 g_free(network->wifi.security);
1843                 network->wifi.security = g_strdup(value);
1844         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1845                 g_free(network->wifi.passphrase);
1846                 network->wifi.passphrase = g_strdup(value);
1847         } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) {
1848                 g_free(network->wifi.agent_passphrase);
1849                 network->wifi.agent_passphrase = g_strdup(value);
1850         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1851                 g_free(network->wifi.eap);
1852                 network->wifi.eap = g_strdup(value);
1853         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1854                 g_free(network->wifi.identity);
1855                 network->wifi.identity = g_strdup(value);
1856         } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) {
1857                 g_free(network->wifi.agent_identity);
1858                 network->wifi.agent_identity = g_strdup(value);
1859         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1860                 g_free(network->wifi.ca_cert_path);
1861                 network->wifi.ca_cert_path = g_strdup(value);
1862         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1863                 g_free(network->wifi.client_cert_path);
1864                 network->wifi.client_cert_path = g_strdup(value);
1865         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1866                 g_free(network->wifi.private_key_path);
1867                 network->wifi.private_key_path = g_strdup(value);
1868         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1869                 g_free(network->wifi.private_key_passphrase);
1870                 network->wifi.private_key_passphrase = g_strdup(value);
1871         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1872                 g_free(network->wifi.phase2_auth);
1873                 network->wifi.phase2_auth = g_strdup(value);
1874         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1875                 g_free(network->wifi.pin_wps);
1876                 network->wifi.pin_wps = g_strdup(value);
1877         } else {
1878                 return -EINVAL;
1879         }
1880
1881         return 0;
1882 }
1883
1884 /**
1885  * connman_network_get_string:
1886  * @network: network structure
1887  * @key: unique identifier
1888  *
1889  * Get string value for specific key
1890  */
1891 const char *connman_network_get_string(struct connman_network *network,
1892                                                         const char *key)
1893 {
1894         DBG("network %p key %s", network, key);
1895
1896         if (g_str_equal(key, "Path") == TRUE)
1897                 return network->path;
1898         else if (g_str_equal(key, "Name") == TRUE)
1899                 return network->name;
1900         else if (g_str_equal(key, "Node") == TRUE)
1901                 return network->node;
1902         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1903                 return network->wifi.mode;
1904         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1905                 return network->wifi.security;
1906         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1907                 return network->wifi.passphrase;
1908         else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE)
1909                 return network->wifi.agent_passphrase;
1910         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1911                 return network->wifi.eap;
1912         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1913                 return network->wifi.identity;
1914         else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE)
1915                 return network->wifi.agent_identity;
1916         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1917                 return network->wifi.ca_cert_path;
1918         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1919                 return network->wifi.client_cert_path;
1920         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1921                 return network->wifi.private_key_path;
1922         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1923                 return network->wifi.private_key_passphrase;
1924         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1925                 return network->wifi.phase2_auth;
1926         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1927                 return network->wifi.pin_wps;
1928
1929         return NULL;
1930 }
1931
1932 /**
1933  * connman_network_set_bool:
1934  * @network: network structure
1935  * @key: unique identifier
1936  * @value: boolean value
1937  *
1938  * Set boolean value for specific key
1939  */
1940 int connman_network_set_bool(struct connman_network *network,
1941                                         const char *key, connman_bool_t value)
1942 {
1943         DBG("network %p key %s value %d", network, key, value);
1944
1945         if (g_strcmp0(key, "Roaming") == 0)
1946                 network->roaming = value;
1947         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1948                 network->wifi.wps = value;
1949         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1950                 network->wifi.use_wps = value;
1951
1952         return -EINVAL;
1953 }
1954
1955 /**
1956  * connman_network_get_bool:
1957  * @network: network structure
1958  * @key: unique identifier
1959  *
1960  * Get boolean value for specific key
1961  */
1962 connman_bool_t connman_network_get_bool(struct connman_network *network,
1963                                                         const char *key)
1964 {
1965         DBG("network %p key %s", network, key);
1966
1967         if (g_str_equal(key, "Roaming") == TRUE)
1968                 return network->roaming;
1969         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
1970                 return network->wifi.wps;
1971         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
1972                 return network->wifi.use_wps;
1973
1974         return FALSE;
1975 }
1976
1977 /**
1978  * connman_network_set_blob:
1979  * @network: network structure
1980  * @key: unique identifier
1981  * @data: blob data
1982  * @size: blob size
1983  *
1984  * Set binary blob value for specific key
1985  */
1986 int connman_network_set_blob(struct connman_network *network,
1987                         const char *key, const void *data, unsigned int size)
1988 {
1989         DBG("network %p key %s size %d", network, key, size);
1990
1991         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1992                 g_free(network->wifi.ssid);
1993                 network->wifi.ssid = g_try_malloc(size);
1994                 if (network->wifi.ssid != NULL) {
1995                         memcpy(network->wifi.ssid, data, size);
1996                         network->wifi.ssid_len = size;
1997                 } else
1998                         network->wifi.ssid_len = 0;
1999         } else {
2000                 return -EINVAL;
2001         }
2002
2003         return 0;
2004 }
2005
2006 /**
2007  * connman_network_get_blob:
2008  * @network: network structure
2009  * @key: unique identifier
2010  * @size: pointer to blob size
2011  *
2012  * Get binary blob value for specific key
2013  */
2014 const void *connman_network_get_blob(struct connman_network *network,
2015                                         const char *key, unsigned int *size)
2016 {
2017         DBG("network %p key %s", network, key);
2018
2019         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
2020                 if (size != NULL)
2021                         *size = network->wifi.ssid_len;
2022                 return network->wifi.ssid;
2023         }
2024
2025         return NULL;
2026 }
2027
2028 void __connman_network_set_device(struct connman_network *network,
2029                                         struct connman_device *device)
2030 {
2031         if (network->device == device)
2032                 return;
2033
2034         if (network->device != NULL)
2035                 network_remove(network);
2036
2037         network->device = device;
2038
2039         if (network->device != NULL)
2040                 network_probe(network);
2041 }
2042
2043 /**
2044  * connman_network_get_device:
2045  * @network: network structure
2046  *
2047  * Get parent device of network
2048  */
2049 struct connman_device *connman_network_get_device(struct connman_network *network)
2050 {
2051         return network->device;
2052 }
2053
2054 /**
2055  * connman_network_get_data:
2056  * @network: network structure
2057  *
2058  * Get private network data pointer
2059  */
2060 void *connman_network_get_data(struct connman_network *network)
2061 {
2062         return network->driver_data;
2063 }
2064
2065 /**
2066  * connman_network_set_data:
2067  * @network: network structure
2068  * @data: data pointer
2069  *
2070  * Set private network data pointer
2071  */
2072 void connman_network_set_data(struct connman_network *network, void *data)
2073 {
2074         network->driver_data = data;
2075 }
2076
2077 void connman_network_update(struct connman_network *network)
2078 {
2079         switch (network->type) {
2080         case CONNMAN_NETWORK_TYPE_UNKNOWN:
2081         case CONNMAN_NETWORK_TYPE_VENDOR:
2082                 return;
2083         case CONNMAN_NETWORK_TYPE_ETHERNET:
2084         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
2085         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
2086         case CONNMAN_NETWORK_TYPE_CELLULAR:
2087         case CONNMAN_NETWORK_TYPE_WIFI:
2088                 break;
2089         }
2090
2091         if (network->group != NULL)
2092                 __connman_service_update_from_network(network);
2093 }
2094
2095 int __connman_network_init(void)
2096 {
2097         DBG("");
2098
2099         return 0;
2100 }
2101
2102 void __connman_network_cleanup(void)
2103 {
2104         DBG("");
2105 }