4e053fc9caa9c49880122777ef61b739db1fab77
[platform/upstream/connman.git] / src / technology.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <string.h>
28
29 #include <gdbus.h>
30
31 #include "connman.h"
32
33 static DBusConnection *connection;
34
35 static GSList *technology_list = NULL;
36
37 /*
38  * List of devices with no technology associated with them either because of
39  * no compiled in support or the driver is not yet loaded.
40 */
41 static GSList *techless_device_list = NULL;
42 static GHashTable *rfkill_list;
43
44 static bool global_offlinemode;
45
46 struct connman_rfkill {
47         unsigned int index;
48         enum connman_service_type type;
49         bool softblock;
50         bool hardblock;
51 };
52
53 struct connman_technology {
54         int refcount;
55         enum connman_service_type type;
56         char *path;
57         GSList *device_list;
58         bool enabled;
59         char *regdom;
60         bool connected;
61
62         bool tethering;
63         bool tethering_persistent; /* Tells the save status, needed
64                                               * as offline mode might set
65                                               * tethering OFF.
66                                               */
67         char *tethering_ident;
68         char *tethering_passphrase;
69
70         bool enable_persistent; /* Save the tech state */
71
72         GSList *driver_list;
73
74         DBusMessage *pending_reply;
75         guint pending_timeout;
76
77         GSList *scan_pending;
78
79         bool rfkill_driven;
80         bool softblocked;
81         bool hardblocked;
82         bool dbus_registered;
83 };
84
85 static GSList *driver_list = NULL;
86
87 static int technology_enabled(struct connman_technology *technology);
88 static int technology_disabled(struct connman_technology *technology);
89
90 static gint compare_priority(gconstpointer a, gconstpointer b)
91 {
92         const struct connman_technology_driver *driver1 = a;
93         const struct connman_technology_driver *driver2 = b;
94
95         return driver2->priority - driver1->priority;
96 }
97
98 static void rfkill_check(gpointer key, gpointer value, gpointer user_data)
99 {
100         struct connman_rfkill *rfkill = value;
101         enum connman_service_type type = GPOINTER_TO_INT(user_data);
102
103         /* Calling _technology_add_rfkill will update the tech. */
104         if (rfkill->type == type)
105                 __connman_technology_add_rfkill(rfkill->index, type,
106                                 rfkill->softblock, rfkill->hardblock);
107 }
108
109 bool
110 connman_technology_is_tethering_allowed(enum connman_service_type type)
111 {
112         static char *allowed_default[] = { "wifi", "bluetooth", "gadget",
113                                            NULL };
114         const char *type_str = __connman_service_type2string(type);
115         char **allowed;
116         int i;
117
118         if (!type_str)
119                 return false;
120
121         allowed = connman_setting_get_string_list("TetheringTechnologies");
122         if (!allowed)
123                 allowed = allowed_default;
124
125         for (i = 0; allowed[i]; i++) {
126                 if (g_strcmp0(allowed[i], type_str) == 0)
127                         return true;
128         }
129
130         return false;
131 }
132
133 static const char *get_name(enum connman_service_type type)
134 {
135         switch (type) {
136         case CONNMAN_SERVICE_TYPE_UNKNOWN:
137         case CONNMAN_SERVICE_TYPE_SYSTEM:
138         case CONNMAN_SERVICE_TYPE_GPS:
139         case CONNMAN_SERVICE_TYPE_VPN:
140                 break;
141         case CONNMAN_SERVICE_TYPE_GADGET:
142                 return "Gadget";
143         case CONNMAN_SERVICE_TYPE_ETHERNET:
144                 return "Wired";
145         case CONNMAN_SERVICE_TYPE_WIFI:
146                 return "WiFi";
147         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
148                 return "Bluetooth";
149         case CONNMAN_SERVICE_TYPE_CELLULAR:
150                 return "Cellular";
151         case CONNMAN_SERVICE_TYPE_P2P:
152                 return "P2P";
153         }
154
155         return NULL;
156 }
157
158 static void technology_save(struct connman_technology *technology)
159 {
160         GKeyFile *keyfile;
161         gchar *identifier;
162         const char *name = get_name(technology->type);
163
164         DBG("technology %p type %d name %s", technology, technology->type,
165                                                                         name);
166         if (!name)
167                 return;
168
169         keyfile = __connman_storage_load_global();
170         if (!keyfile)
171                 keyfile = g_key_file_new();
172
173         identifier = g_strdup_printf("%s", name);
174         if (!identifier)
175                 goto done;
176
177         g_key_file_set_boolean(keyfile, identifier, "Enable",
178                                 technology->enable_persistent);
179
180         g_key_file_set_boolean(keyfile, identifier, "Tethering",
181                                 technology->tethering_persistent);
182
183         if (technology->tethering_ident)
184                 g_key_file_set_string(keyfile, identifier,
185                                         "Tethering.Identifier",
186                                         technology->tethering_ident);
187
188         if (technology->tethering_passphrase)
189                 g_key_file_set_string(keyfile, identifier,
190                                         "Tethering.Passphrase",
191                                         technology->tethering_passphrase);
192
193 done:
194         g_free(identifier);
195
196         __connman_storage_save_global(keyfile);
197
198         g_key_file_free(keyfile);
199 }
200
201 static void tethering_changed(struct connman_technology *technology)
202 {
203         dbus_bool_t tethering = technology->tethering;
204
205         connman_dbus_property_changed_basic(technology->path,
206                                 CONNMAN_TECHNOLOGY_INTERFACE, "Tethering",
207                                                 DBUS_TYPE_BOOLEAN, &tethering);
208
209         technology_save(technology);
210 }
211
212 int connman_technology_tethering_notify(struct connman_technology *technology,
213                                                         bool enabled)
214 {
215         int err;
216
217         DBG("technology %p enabled %u", technology, enabled);
218
219         if (technology->tethering == enabled)
220                 return -EALREADY;
221
222         if (enabled) {
223                 err = __connman_tethering_set_enabled();
224                 if (err < 0)
225                         return err;
226         } else
227                 __connman_tethering_set_disabled();
228
229         technology->tethering = enabled;
230         tethering_changed(technology);
231
232         return 0;
233 }
234
235 static int set_tethering(struct connman_technology *technology,
236                                 bool enabled)
237 {
238         int result = -EOPNOTSUPP;
239         int err;
240         const char *ident, *passphrase, *bridge;
241         GSList *tech_drivers;
242
243         ident = technology->tethering_ident;
244         passphrase = technology->tethering_passphrase;
245
246         __sync_synchronize();
247         if (!technology->enabled)
248                 return -EACCES;
249
250         bridge = __connman_tethering_get_bridge();
251         if (!bridge)
252                 return -EOPNOTSUPP;
253
254         if (technology->type == CONNMAN_SERVICE_TYPE_WIFI &&
255             (!ident || !passphrase))
256                 return -EINVAL;
257
258         for (tech_drivers = technology->driver_list; tech_drivers;
259              tech_drivers = g_slist_next(tech_drivers)) {
260                 struct connman_technology_driver *driver = tech_drivers->data;
261
262                 if (!driver || !driver->set_tethering)
263                         continue;
264
265                 err = driver->set_tethering(technology, ident, passphrase,
266                                 bridge, enabled);
267
268                 if (result == -EINPROGRESS)
269                         continue;
270
271                 if (err == -EINPROGRESS || err == 0)
272                         result = err;
273         }
274
275         return result;
276 }
277
278 void connman_technology_regdom_notify(struct connman_technology *technology,
279                                                         const char *alpha2)
280 {
281         DBG("");
282
283         if (!alpha2)
284                 connman_error("Failed to set regulatory domain");
285         else
286                 DBG("Regulatory domain set to %s", alpha2);
287
288         g_free(technology->regdom);
289         technology->regdom = g_strdup(alpha2);
290 }
291
292 static int set_regdom_by_device(struct connman_technology *technology,
293                                                         const char *alpha2)
294 {
295         GSList *list;
296
297         for (list = technology->device_list; list; list = list->next) {
298                 struct connman_device *device = list->data;
299
300                 if (connman_device_set_regdom(device, alpha2) != 0)
301                         return -ENOTSUP;
302         }
303
304         return 0;
305 }
306
307 int connman_technology_set_regdom(const char *alpha2)
308 {
309         GSList *list, *tech_drivers;
310
311         for (list = technology_list; list; list = list->next) {
312                 struct connman_technology *technology = list->data;
313
314                 if (set_regdom_by_device(technology, alpha2) != 0) {
315
316                         for (tech_drivers = technology->driver_list;
317                              tech_drivers;
318                              tech_drivers = g_slist_next(tech_drivers)) {
319
320                                 struct connman_technology_driver *driver =
321                                         tech_drivers->data;
322
323                                 if (driver->set_regdom)
324                                         driver->set_regdom(technology, alpha2);
325                         }
326                 }
327         }
328
329         return 0;
330 }
331
332 static struct connman_technology *technology_find(enum connman_service_type type)
333 {
334         GSList *list;
335
336         DBG("type %d", type);
337
338         for (list = technology_list; list; list = list->next) {
339                 struct connman_technology *technology = list->data;
340
341                 if (technology->type == type)
342                         return technology;
343         }
344
345         return NULL;
346 }
347
348 enum connman_service_type connman_technology_get_type
349                                 (struct connman_technology *technology)
350 {
351         if (!technology)
352                 return CONNMAN_SERVICE_TYPE_UNKNOWN;
353
354         return technology->type;
355 }
356
357 bool connman_technology_get_wifi_tethering(const char **ssid,
358                                                         const char **psk)
359 {
360         struct connman_technology *technology;
361
362         if (!ssid || !psk)
363                 return false;
364
365         *ssid = *psk = NULL;
366
367         technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
368         if (!technology)
369                 return false;
370
371         if (!technology->tethering)
372                 return false;
373
374         *ssid = technology->tethering_ident;
375         *psk = technology->tethering_passphrase;
376
377         return true;
378 }
379
380 static void free_rfkill(gpointer data)
381 {
382         struct connman_rfkill *rfkill = data;
383
384         g_free(rfkill);
385 }
386
387 static void technology_load(struct connman_technology *technology)
388 {
389         GKeyFile *keyfile;
390         gchar *identifier;
391         GError *error = NULL;
392         bool enable, need_saving = false;
393
394         DBG("technology %p", technology);
395
396         keyfile = __connman_storage_load_global();
397         /* Fallback on disabling technology if file not found. */
398         if (!keyfile) {
399                 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
400                         /* We enable ethernet by default */
401                         technology->enable_persistent = true;
402                 else
403                         technology->enable_persistent = false;
404                 return;
405         }
406
407         identifier = g_strdup_printf("%s", get_name(technology->type));
408         if (!identifier)
409                 goto done;
410
411         enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
412         if (!error)
413                 technology->enable_persistent = enable;
414         else {
415                 if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET)
416                         technology->enable_persistent = true;
417                 else
418                         technology->enable_persistent = false;
419
420                 need_saving = true;
421                 g_clear_error(&error);
422         }
423
424         enable = g_key_file_get_boolean(keyfile, identifier,
425                                         "Tethering", &error);
426         if (!error)
427                 technology->tethering_persistent = enable;
428         else {
429                 need_saving = true;
430                 g_clear_error(&error);
431         }
432
433         if (need_saving)
434                 technology_save(technology);
435
436         technology->tethering_ident = g_key_file_get_string(keyfile,
437                                 identifier, "Tethering.Identifier", NULL);
438
439         technology->tethering_passphrase = g_key_file_get_string(keyfile,
440                                 identifier, "Tethering.Passphrase", NULL);
441 done:
442         g_free(identifier);
443
444         g_key_file_free(keyfile);
445 }
446
447 bool __connman_technology_get_offlinemode(void)
448 {
449         return global_offlinemode;
450 }
451
452 static void connman_technology_save_offlinemode(void)
453 {
454         GKeyFile *keyfile;
455         GError *error = NULL;
456         bool offlinemode;
457
458         keyfile = __connman_storage_load_global();
459
460         if (!keyfile) {
461                 keyfile = g_key_file_new();
462                 g_key_file_set_boolean(keyfile, "global",
463                                         "OfflineMode", global_offlinemode);
464
465                 __connman_storage_save_global(keyfile);
466         }
467         else {
468                 offlinemode = g_key_file_get_boolean(keyfile, "global",
469                                                 "OfflineMode", &error);
470
471                 if (error || offlinemode != global_offlinemode) {
472                         g_key_file_set_boolean(keyfile, "global",
473                                         "OfflineMode", global_offlinemode);
474                         if (error)
475                                 g_clear_error(&error);
476
477                         __connman_storage_save_global(keyfile);
478                 }
479         }
480
481         g_key_file_free(keyfile);
482 }
483
484 static bool connman_technology_load_offlinemode(void)
485 {
486         GKeyFile *keyfile;
487         GError *error = NULL;
488         bool offlinemode;
489
490         /* If there is a error, we enable offlinemode */
491         keyfile = __connman_storage_load_global();
492         if (!keyfile)
493                 return false;
494
495         offlinemode = g_key_file_get_boolean(keyfile, "global",
496                                                 "OfflineMode", &error);
497         if (error) {
498                 offlinemode = false;
499                 g_clear_error(&error);
500         }
501
502         g_key_file_free(keyfile);
503
504         return offlinemode;
505 }
506
507 static void append_properties(DBusMessageIter *iter,
508                 struct connman_technology *technology)
509 {
510         DBusMessageIter dict;
511         dbus_bool_t val;
512         const char *str;
513
514         connman_dbus_dict_open(iter, &dict);
515
516         str = get_name(technology->type);
517         if (str)
518                 connman_dbus_dict_append_basic(&dict, "Name",
519                                                 DBUS_TYPE_STRING, &str);
520
521         str = __connman_service_type2string(technology->type);
522         if (str)
523                 connman_dbus_dict_append_basic(&dict, "Type",
524                                                 DBUS_TYPE_STRING, &str);
525
526         __sync_synchronize();
527         val = technology->enabled;
528         connman_dbus_dict_append_basic(&dict, "Powered",
529                                         DBUS_TYPE_BOOLEAN,
530                                         &val);
531
532         val = technology->connected;
533         connman_dbus_dict_append_basic(&dict, "Connected",
534                                         DBUS_TYPE_BOOLEAN,
535                                         &val);
536
537         val = technology->tethering;
538         connman_dbus_dict_append_basic(&dict, "Tethering",
539                                         DBUS_TYPE_BOOLEAN,
540                                         &val);
541
542         if (technology->tethering_ident)
543                 connman_dbus_dict_append_basic(&dict, "TetheringIdentifier",
544                                         DBUS_TYPE_STRING,
545                                         &technology->tethering_ident);
546
547         if (technology->tethering_passphrase)
548                 connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
549                                         DBUS_TYPE_STRING,
550                                         &technology->tethering_passphrase);
551
552         connman_dbus_dict_close(iter, &dict);
553 }
554
555 static void technology_added_signal(struct connman_technology *technology)
556 {
557         DBusMessage *signal;
558         DBusMessageIter iter;
559
560         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
561                         CONNMAN_MANAGER_INTERFACE, "TechnologyAdded");
562         if (!signal)
563                 return;
564
565         dbus_message_iter_init_append(signal, &iter);
566         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
567                                                         &technology->path);
568         append_properties(&iter, technology);
569
570         dbus_connection_send(connection, signal, NULL);
571         dbus_message_unref(signal);
572 }
573
574 static void technology_removed_signal(struct connman_technology *technology)
575 {
576         g_dbus_emit_signal(connection, CONNMAN_MANAGER_PATH,
577                         CONNMAN_MANAGER_INTERFACE, "TechnologyRemoved",
578                         DBUS_TYPE_OBJECT_PATH, &technology->path,
579                         DBUS_TYPE_INVALID);
580 }
581
582 static DBusMessage *get_properties(DBusConnection *conn,
583                                         DBusMessage *message, void *user_data)
584 {
585         struct connman_technology *technology = user_data;
586         DBusMessage *reply;
587         DBusMessageIter iter;
588
589         reply = dbus_message_new_method_return(message);
590         if (!reply)
591                 return NULL;
592
593         dbus_message_iter_init_append(reply, &iter);
594         append_properties(&iter, technology);
595
596         return reply;
597 }
598
599 void __connman_technology_list_struct(DBusMessageIter *array)
600 {
601         GSList *list;
602         DBusMessageIter entry;
603
604         for (list = technology_list; list; list = list->next) {
605                 struct connman_technology *technology = list->data;
606
607                 if (!technology->path ||
608                                 (technology->rfkill_driven &&
609                                  technology->hardblocked))
610                         continue;
611
612                 dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
613                                 NULL, &entry);
614                 dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
615                                 &technology->path);
616                 append_properties(&entry, technology);
617                 dbus_message_iter_close_container(array, &entry);
618         }
619 }
620
621 static gboolean technology_pending_reply(gpointer user_data)
622 {
623         struct connman_technology *technology = user_data;
624         DBusMessage *reply;
625
626         /* Power request timed out, send ETIMEDOUT. */
627         if (technology->pending_reply) {
628                 reply = __connman_error_failed(technology->pending_reply, ETIMEDOUT);
629                 if (reply)
630                         g_dbus_send_message(connection, reply);
631
632                 dbus_message_unref(technology->pending_reply);
633                 technology->pending_reply = NULL;
634                 technology->pending_timeout = 0;
635         }
636
637         return FALSE;
638 }
639
640 static int technology_affect_devices(struct connman_technology *technology,
641                                                 bool enable_device)
642 {
643         int err = 0, err_dev;
644         GSList *list;
645
646         if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
647                 if (enable_device)
648                         __connman_technology_enabled(technology->type);
649                 else
650                         __connman_technology_disabled(technology->type);
651                 return 0;
652         }
653
654         for (list = technology->device_list; list; list = list->next) {
655                 struct connman_device *device = list->data;
656
657                 if (enable_device)
658                         err_dev = __connman_device_enable(device);
659                 else
660                         err_dev = __connman_device_disable(device);
661
662                 if (err_dev < 0 && err_dev != -EALREADY)
663                         err = err_dev;
664         }
665
666         return err;
667 }
668
669 static void powered_changed(struct connman_technology *technology)
670 {
671         dbus_bool_t enabled;
672
673         if (!technology->dbus_registered)
674                 return;
675
676         if (technology->pending_reply) {
677                 g_dbus_send_reply(connection,
678                                 technology->pending_reply, DBUS_TYPE_INVALID);
679                 dbus_message_unref(technology->pending_reply);
680                 technology->pending_reply = NULL;
681
682                 g_source_remove(technology->pending_timeout);
683                 technology->pending_timeout = 0;
684         }
685
686         __sync_synchronize();
687         enabled = technology->enabled;
688         connman_dbus_property_changed_basic(technology->path,
689                         CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
690                         DBUS_TYPE_BOOLEAN, &enabled);
691 }
692
693 static void enable_tethering(struct connman_technology *technology)
694 {
695         int ret;
696
697         if (!connman_setting_get_bool("PersistentTetheringMode"))
698                 return;
699
700         ret = set_tethering(technology, true);
701         if (ret < 0 && ret != -EALREADY)
702                 DBG("Cannot enable tethering yet for %s (%d/%s)",
703                         get_name(technology->type),
704                         -ret, strerror(-ret));
705 }
706
707 static int technology_enabled(struct connman_technology *technology)
708 {
709         __sync_synchronize();
710         if (technology->enabled)
711                 return -EALREADY;
712
713         technology->enabled = true;
714
715         if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
716                 struct connman_technology *p2p;
717
718                 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
719                 if (p2p && !p2p->enabled && p2p->enable_persistent)
720                         technology_enabled(p2p);
721         }
722
723         if (technology->tethering_persistent)
724                 enable_tethering(technology);
725
726         powered_changed(technology);
727
728         return 0;
729 }
730
731 static int technology_enable(struct connman_technology *technology)
732 {
733         int err = 0;
734         int err_dev;
735
736         DBG("technology %p enable", technology);
737
738         __sync_synchronize();
739
740         if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
741                 struct connman_technology *wifi;
742
743                 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
744                 if (wifi && wifi->enabled)
745                         return technology_enabled(technology);
746                 return 0;
747         }
748
749         if (technology->enabled)
750                 return -EALREADY;
751
752         if (technology->pending_reply)
753                 return -EBUSY;
754
755         if (connman_setting_get_bool("PersistentTetheringMode") &&
756                                         technology->tethering)
757                 set_tethering(technology, true);
758
759         if (technology->rfkill_driven)
760                 err = __connman_rfkill_block(technology->type, false);
761
762         err_dev = technology_affect_devices(technology, true);
763
764         if (!technology->rfkill_driven)
765                 err = err_dev;
766
767         return err;
768 }
769
770 static int technology_disabled(struct connman_technology *technology)
771 {
772         __sync_synchronize();
773         if (!technology->enabled)
774                 return -EALREADY;
775
776         technology->enabled = false;
777
778         powered_changed(technology);
779
780         return 0;
781 }
782
783 static int technology_disable(struct connman_technology *technology)
784 {
785         int err;
786
787         DBG("technology %p disable", technology);
788
789         __sync_synchronize();
790
791         if (technology->type == CONNMAN_SERVICE_TYPE_P2P) {
792                 technology->enable_persistent = false;
793                 __connman_device_stop_scan(CONNMAN_SERVICE_TYPE_P2P);
794                 __connman_peer_disconnect_all();
795                 return technology_disabled(technology);
796         } else if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
797                 struct connman_technology *p2p;
798
799                 p2p = technology_find(CONNMAN_SERVICE_TYPE_P2P);
800                 if (p2p && p2p->enabled) {
801                         p2p->enable_persistent = true;
802                         technology_disabled(p2p);
803                 }
804         }
805
806         if (!technology->enabled)
807                 return -EALREADY;
808
809         if (technology->pending_reply)
810                 return -EBUSY;
811
812         if (technology->tethering)
813                 set_tethering(technology, false);
814
815         err = technology_affect_devices(technology, false);
816
817         if (technology->rfkill_driven)
818                 err = __connman_rfkill_block(technology->type, true);
819
820         return err;
821 }
822
823 static DBusMessage *set_powered(struct connman_technology *technology,
824                                 DBusMessage *msg, bool powered)
825 {
826         DBusMessage *reply = NULL;
827         int err = 0;
828
829         if (technology->rfkill_driven && technology->hardblocked) {
830                 err = -EACCES;
831                 goto make_reply;
832         }
833
834         if (powered)
835                 err = technology_enable(technology);
836         else
837                 err = technology_disable(technology);
838
839         if (err != -EBUSY) {
840                 technology->enable_persistent = powered;
841                 technology_save(technology);
842         }
843
844 make_reply:
845         if (err == -EINPROGRESS) {
846                 technology->pending_reply = dbus_message_ref(msg);
847                 technology->pending_timeout = g_timeout_add_seconds(10,
848                                         technology_pending_reply, technology);
849         } else if (err == -EALREADY) {
850                 if (powered)
851                         reply = __connman_error_already_enabled(msg);
852                 else
853                         reply = __connman_error_already_disabled(msg);
854         } else if (err < 0)
855                 reply = __connman_error_failed(msg, -err);
856         else
857                 reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
858
859         return reply;
860 }
861
862 static DBusMessage *set_property(DBusConnection *conn,
863                                         DBusMessage *msg, void *data)
864 {
865         struct connman_technology *technology = data;
866         DBusMessageIter iter, value;
867         const char *name;
868         int type, err;
869
870         DBG("conn %p", conn);
871
872         if (!dbus_message_iter_init(msg, &iter))
873                 return __connman_error_invalid_arguments(msg);
874
875         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
876                 return __connman_error_invalid_arguments(msg);
877
878         dbus_message_iter_get_basic(&iter, &name);
879         dbus_message_iter_next(&iter);
880
881         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
882                 return __connman_error_invalid_arguments(msg);
883
884         dbus_message_iter_recurse(&iter, &value);
885
886         type = dbus_message_iter_get_arg_type(&value);
887
888         DBG("property %s", name);
889
890         if (g_str_equal(name, "Tethering")) {
891                 dbus_bool_t tethering;
892                 int err;
893
894                 if (type != DBUS_TYPE_BOOLEAN)
895                         return __connman_error_invalid_arguments(msg);
896
897                 if (!connman_technology_is_tethering_allowed(technology->type)) {
898                         DBG("%s tethering not allowed by config file",
899                                 __connman_service_type2string(technology->type));
900                         return __connman_error_not_supported(msg);
901                 }
902
903                 dbus_message_iter_get_basic(&value, &tethering);
904
905                 if (technology->tethering == tethering) {
906                         if (!tethering)
907                                 return __connman_error_already_disabled(msg);
908                         else
909                                 return __connman_error_already_enabled(msg);
910                 }
911
912                 err = set_tethering(technology, tethering);
913                 if (err < 0)
914                         return __connman_error_failed(msg, -err);
915
916                 technology->tethering_persistent = tethering;
917
918                 technology_save(technology);
919
920         } else if (g_str_equal(name, "TetheringIdentifier")) {
921                 const char *str;
922
923                 dbus_message_iter_get_basic(&value, &str);
924
925                 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
926                         return __connman_error_not_supported(msg);
927
928                 if (strlen(str) < 1 || strlen(str) > 32)
929                         return __connman_error_invalid_arguments(msg);
930
931                 if (g_strcmp0(technology->tethering_ident, str) != 0) {
932                         g_free(technology->tethering_ident);
933                         technology->tethering_ident = g_strdup(str);
934                         technology_save(technology);
935
936                         connman_dbus_property_changed_basic(technology->path,
937                                                 CONNMAN_TECHNOLOGY_INTERFACE,
938                                                 "TetheringIdentifier",
939                                                 DBUS_TYPE_STRING,
940                                                 &technology->tethering_ident);
941                 }
942         } else if (g_str_equal(name, "TetheringPassphrase")) {
943                 const char *str;
944
945                 dbus_message_iter_get_basic(&value, &str);
946
947                 if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
948                         return __connman_error_not_supported(msg);
949
950                 err = __connman_service_check_passphrase(CONNMAN_SERVICE_SECURITY_PSK,
951                                                         str);
952                 if (err < 0)
953                         return __connman_error_passphrase_required(msg);
954
955                 if (g_strcmp0(technology->tethering_passphrase, str) != 0) {
956                         g_free(technology->tethering_passphrase);
957                         technology->tethering_passphrase = g_strdup(str);
958                         technology_save(technology);
959
960                         connman_dbus_property_changed_basic(technology->path,
961                                         CONNMAN_TECHNOLOGY_INTERFACE,
962                                         "TetheringPassphrase",
963                                         DBUS_TYPE_STRING,
964                                         &technology->tethering_passphrase);
965                 }
966         } else if (g_str_equal(name, "Powered")) {
967                 dbus_bool_t enable;
968
969                 if (type != DBUS_TYPE_BOOLEAN)
970                         return __connman_error_invalid_arguments(msg);
971
972                 dbus_message_iter_get_basic(&value, &enable);
973
974                 return set_powered(technology, msg, enable);
975         } else
976                 return __connman_error_invalid_property(msg);
977
978         return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
979 }
980
981 static void reply_scan_pending(struct connman_technology *technology, int err)
982 {
983         DBusMessage *reply;
984
985         DBG("technology %p err %d", technology, err);
986
987         while (technology->scan_pending) {
988                 DBusMessage *msg = technology->scan_pending->data;
989
990                 DBG("reply to %s", dbus_message_get_sender(msg));
991
992                 if (err == 0)
993                         reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
994                 else
995                         reply = __connman_error_failed(msg, -err);
996                 g_dbus_send_message(connection, reply);
997                 dbus_message_unref(msg);
998
999                 technology->scan_pending =
1000                         g_slist_delete_link(technology->scan_pending,
1001                                         technology->scan_pending);
1002         }
1003 }
1004
1005 void __connman_technology_scan_started(struct connman_device *device)
1006 {
1007         DBG("device %p", device);
1008 }
1009
1010 void __connman_technology_scan_stopped(struct connman_device *device,
1011                                         enum connman_service_type type)
1012 {
1013         int count = 0;
1014         struct connman_technology *technology;
1015         GSList *list;
1016
1017         technology = technology_find(type);
1018
1019         DBG("technology %p device %p", technology, device);
1020
1021         if (!technology)
1022                 return;
1023
1024         for (list = technology->device_list; list; list = list->next) {
1025                 struct connman_device *other_device = list->data;
1026
1027                 if (device == other_device)
1028                         continue;
1029
1030                 if (connman_device_get_scanning(other_device, type))
1031                         count += 1;
1032         }
1033
1034         if (count == 0)
1035                 reply_scan_pending(technology, 0);
1036 }
1037
1038 void __connman_technology_notify_regdom_by_device(struct connman_device *device,
1039                                                 int result, const char *alpha2)
1040 {
1041         bool regdom_set = false;
1042         struct connman_technology *technology;
1043         enum connman_service_type type;
1044         GSList *tech_drivers;
1045
1046         type = __connman_device_get_service_type(device);
1047         technology = technology_find(type);
1048
1049         if (!technology)
1050                 return;
1051
1052         if (result < 0) {
1053
1054                 for (tech_drivers = technology->driver_list;
1055                      tech_drivers;
1056                      tech_drivers = g_slist_next(tech_drivers)) {
1057                         struct connman_technology_driver *driver =
1058                                 tech_drivers->data;
1059
1060                         if (driver->set_regdom) {
1061                                 driver->set_regdom(technology, alpha2);
1062                                 regdom_set = true;
1063                         }
1064
1065                 }
1066
1067                 if (!regdom_set)
1068                         alpha2 = NULL;
1069         }
1070
1071         connman_technology_regdom_notify(technology, alpha2);
1072 }
1073
1074 static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
1075 {
1076         struct connman_technology *technology = data;
1077         int err;
1078
1079         DBG("technology %p request from %s", technology,
1080                         dbus_message_get_sender(msg));
1081
1082         if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
1083                                 !technology->enabled)
1084                 return __connman_error_permission_denied(msg);
1085
1086         dbus_message_ref(msg);
1087         technology->scan_pending =
1088                 g_slist_prepend(technology->scan_pending, msg);
1089
1090         err = __connman_device_request_scan_full(technology->type);
1091         if (err < 0)
1092                 reply_scan_pending(technology, err);
1093
1094         return NULL;
1095 }
1096
1097 static const GDBusMethodTable technology_methods[] = {
1098         { GDBUS_DEPRECATED_METHOD("GetProperties",
1099                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1100                         get_properties) },
1101         { GDBUS_ASYNC_METHOD("SetProperty",
1102                         GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
1103                         NULL, set_property) },
1104         { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
1105         { },
1106 };
1107
1108 static const GDBusSignalTable technology_signals[] = {
1109         { GDBUS_SIGNAL("PropertyChanged",
1110                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
1111         { },
1112 };
1113
1114 static bool technology_dbus_register(struct connman_technology *technology)
1115 {
1116         if (technology->dbus_registered ||
1117                                 (technology->rfkill_driven &&
1118                                  technology->hardblocked))
1119                 return true;
1120
1121         if (!g_dbus_register_interface(connection, technology->path,
1122                                         CONNMAN_TECHNOLOGY_INTERFACE,
1123                                         technology_methods, technology_signals,
1124                                         NULL, technology, NULL)) {
1125                 connman_error("Failed to register %s", technology->path);
1126                 return false;
1127         }
1128
1129         technology_added_signal(technology);
1130         technology->dbus_registered = true;
1131
1132         return true;
1133 }
1134
1135 static void technology_dbus_unregister(struct connman_technology *technology)
1136 {
1137         if (!technology->dbus_registered)
1138                 return;
1139
1140         technology_removed_signal(technology);
1141         g_dbus_unregister_interface(connection, technology->path,
1142                 CONNMAN_TECHNOLOGY_INTERFACE);
1143
1144         technology->dbus_registered = false;
1145 }
1146
1147 static void technology_put(struct connman_technology *technology)
1148 {
1149         DBG("technology %p", technology);
1150
1151         if (__sync_sub_and_fetch(&technology->refcount, 1) > 0)
1152                 return;
1153
1154         reply_scan_pending(technology, -EINTR);
1155
1156         while (technology->driver_list) {
1157                 struct connman_technology_driver *driver;
1158
1159                 driver = technology->driver_list->data;
1160
1161                 if (driver->remove)
1162                         driver->remove(technology);
1163
1164                 technology->driver_list =
1165                         g_slist_delete_link(technology->driver_list,
1166                                         technology->driver_list);
1167         }
1168
1169         technology_list = g_slist_remove(technology_list, technology);
1170
1171         technology_dbus_unregister(technology);
1172
1173         g_slist_free(technology->device_list);
1174
1175     if (technology->pending_reply) {
1176         dbus_message_unref(technology->pending_reply);
1177         technology->pending_reply = NULL;
1178         g_source_remove(technology->pending_timeout);
1179         technology->pending_timeout = 0;
1180     }
1181
1182         g_free(technology->path);
1183         g_free(technology->regdom);
1184         g_free(technology->tethering_ident);
1185         g_free(technology->tethering_passphrase);
1186         g_free(technology);
1187 }
1188
1189 static struct connman_technology *technology_get(enum connman_service_type type)
1190 {
1191         GSList *tech_drivers = NULL;
1192         struct connman_technology_driver *driver;
1193         struct connman_technology *technology;
1194         const char *str;
1195         GSList *list;
1196
1197         DBG("type %d", type);
1198
1199         str = __connman_service_type2string(type);
1200         if (!str)
1201                 return NULL;
1202
1203         technology = technology_find(type);
1204         if (technology) {
1205                 if (type != CONNMAN_SERVICE_TYPE_P2P)
1206                         __sync_fetch_and_add(&technology->refcount, 1);
1207                 return technology;
1208         }
1209
1210         /* First check if we have a driver for this technology type */
1211         for (list = driver_list; list; list = list->next) {
1212                 driver = list->data;
1213
1214                 if (driver->type == type) {
1215                         DBG("technology %p driver %p", technology, driver);
1216                         tech_drivers = g_slist_append(tech_drivers, driver);
1217                 }
1218         }
1219
1220         if (!tech_drivers) {
1221                 DBG("No matching drivers found for %s.",
1222                                 __connman_service_type2string(type));
1223                 return NULL;
1224         }
1225
1226         technology = g_try_new0(struct connman_technology, 1);
1227         if (!technology)
1228                 return NULL;
1229
1230         technology->refcount = 1;
1231         technology->type = type;
1232         technology->path = g_strdup_printf("%s/technology/%s",
1233                                                         CONNMAN_PATH, str);
1234
1235         technology_load(technology);
1236         technology_list = g_slist_prepend(technology_list, technology);
1237         technology->driver_list = tech_drivers;
1238
1239         for (list = tech_drivers; list; list = list->next) {
1240                 driver = list->data;
1241
1242                 if (driver->probe && driver->probe(technology) < 0)
1243                         DBG("Driver probe failed for technology %p",
1244                                         technology);
1245         }
1246
1247         if (!technology_dbus_register(technology)) {
1248                 technology_put(technology);
1249                 return NULL;
1250         }
1251
1252         if (type == CONNMAN_SERVICE_TYPE_P2P) {
1253                 struct connman_technology *wifi;
1254                 bool enable;
1255
1256                 enable = technology->enable_persistent;
1257
1258                 wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
1259                 if (enable && wifi)
1260                         enable = wifi->enabled;
1261
1262                 technology_affect_devices(technology, enable);
1263         }
1264
1265         DBG("technology %p %s", technology, get_name(technology->type));
1266
1267         return technology;
1268 }
1269
1270 int connman_technology_driver_register(struct connman_technology_driver *driver)
1271 {
1272         GSList *list;
1273         struct connman_device *device;
1274         enum connman_service_type type;
1275
1276         for (list = driver_list; list; list = list->next) {
1277                 if (list->data == driver)
1278                         goto exist;
1279         }
1280
1281         DBG("Registering %s driver", driver->name);
1282
1283         driver_list = g_slist_insert_sorted(driver_list, driver,
1284                                                         compare_priority);
1285
1286         /*
1287          * Check for technology less devices if this driver
1288          * can service any of them.
1289         */
1290         for (list = techless_device_list; list; list = list->next) {
1291                 device = list->data;
1292
1293                 type = __connman_device_get_service_type(device);
1294                 if (type != driver->type)
1295                         continue;
1296
1297                 techless_device_list = g_slist_remove(techless_device_list,
1298                                                                 device);
1299
1300                 __connman_technology_add_device(device);
1301         }
1302
1303         /* Check for orphaned rfkill switches. */
1304         g_hash_table_foreach(rfkill_list, rfkill_check,
1305                                         GINT_TO_POINTER(driver->type));
1306
1307 exist:
1308         if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1309                 if (!technology_get(CONNMAN_SERVICE_TYPE_P2P))
1310                         return -ENOMEM;
1311         }
1312
1313         return 0;
1314 }
1315
1316 void connman_technology_driver_unregister(struct connman_technology_driver *driver)
1317 {
1318         GSList *list, *tech_drivers;
1319         struct connman_technology *technology;
1320         struct connman_technology_driver *current;
1321
1322         DBG("Unregistering driver %p name %s", driver, driver->name);
1323
1324         for (list = technology_list; list; list = list->next) {
1325                 technology = list->data;
1326
1327                 for (tech_drivers = technology->driver_list; tech_drivers;
1328                                 tech_drivers = g_slist_next(tech_drivers)) {
1329                         current = tech_drivers->data;
1330                         if (driver != current)
1331                                 continue;
1332
1333                         if (driver->remove)
1334                                 driver->remove(technology);
1335
1336                         technology->driver_list =
1337                                 g_slist_remove(technology->driver_list,
1338                                                                 driver);
1339                         break;
1340                 }
1341         }
1342
1343         driver_list = g_slist_remove(driver_list, driver);
1344
1345         if (driver->type == CONNMAN_SERVICE_TYPE_P2P) {
1346                 technology = technology_find(CONNMAN_SERVICE_TYPE_P2P);
1347                 if (technology)
1348                         technology_put(technology);
1349         }
1350 }
1351
1352 void __connman_technology_add_interface(enum connman_service_type type,
1353                                 int index, const char *ident)
1354 {
1355         struct connman_technology *technology;
1356         GSList *tech_drivers;
1357         struct connman_technology_driver *driver;
1358         char *name;
1359
1360         switch (type) {
1361         case CONNMAN_SERVICE_TYPE_UNKNOWN:
1362         case CONNMAN_SERVICE_TYPE_SYSTEM:
1363                 return;
1364         case CONNMAN_SERVICE_TYPE_ETHERNET:
1365         case CONNMAN_SERVICE_TYPE_WIFI:
1366         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1367         case CONNMAN_SERVICE_TYPE_CELLULAR:
1368         case CONNMAN_SERVICE_TYPE_GPS:
1369         case CONNMAN_SERVICE_TYPE_VPN:
1370         case CONNMAN_SERVICE_TYPE_GADGET:
1371         case CONNMAN_SERVICE_TYPE_P2P:
1372                 break;
1373         }
1374
1375         name = connman_inet_ifname(index);
1376         connman_info("Adding interface %s [ %s ]", name,
1377                                 __connman_service_type2string(type));
1378
1379         technology = technology_find(type);
1380
1381         if (!technology)
1382                 goto out;
1383
1384         for (tech_drivers = technology->driver_list; tech_drivers;
1385              tech_drivers = g_slist_next(tech_drivers)) {
1386                 driver = tech_drivers->data;
1387
1388                 if (driver->add_interface)
1389                         driver->add_interface(technology, index, name, ident);
1390         }
1391
1392         /*
1393          * At this point we can try to enable tethering automatically as
1394          * now the interfaces are set properly.
1395          */
1396         if (technology->tethering_persistent)
1397                 enable_tethering(technology);
1398
1399 out:
1400         g_free(name);
1401 }
1402
1403 void __connman_technology_remove_interface(enum connman_service_type type,
1404                                 int index, const char *ident)
1405 {
1406         struct connman_technology *technology;
1407         GSList *tech_drivers;
1408         struct connman_technology_driver *driver;
1409         char *name;
1410
1411         switch (type) {
1412         case CONNMAN_SERVICE_TYPE_UNKNOWN:
1413         case CONNMAN_SERVICE_TYPE_SYSTEM:
1414                 return;
1415         case CONNMAN_SERVICE_TYPE_ETHERNET:
1416         case CONNMAN_SERVICE_TYPE_WIFI:
1417         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
1418         case CONNMAN_SERVICE_TYPE_CELLULAR:
1419         case CONNMAN_SERVICE_TYPE_GPS:
1420         case CONNMAN_SERVICE_TYPE_VPN:
1421         case CONNMAN_SERVICE_TYPE_GADGET:
1422         case CONNMAN_SERVICE_TYPE_P2P:
1423                 break;
1424         }
1425
1426         name = connman_inet_ifname(index);
1427         connman_info("Remove interface %s [ %s ]", name,
1428                                 __connman_service_type2string(type));
1429         g_free(name);
1430
1431         technology = technology_find(type);
1432
1433         if (!technology)
1434                 return;
1435
1436         for (tech_drivers = technology->driver_list; tech_drivers;
1437              tech_drivers = g_slist_next(tech_drivers)) {
1438                 driver = tech_drivers->data;
1439
1440                 if (driver->remove_interface)
1441                         driver->remove_interface(technology, index);
1442         }
1443 }
1444
1445 int __connman_technology_add_device(struct connman_device *device)
1446 {
1447         struct connman_technology *technology;
1448         enum connman_service_type type;
1449
1450         type = __connman_device_get_service_type(device);
1451
1452         DBG("device %p type %s", device, get_name(type));
1453
1454         technology = technology_get(type);
1455         if (!technology) {
1456                 /*
1457                  * Since no driver can be found for this device at the moment we
1458                  * add it to the techless device list.
1459                 */
1460                 techless_device_list = g_slist_prepend(techless_device_list,
1461                                                                 device);
1462
1463                 return -ENXIO;
1464         }
1465
1466         __sync_synchronize();
1467         if (technology->rfkill_driven) {
1468                 if (technology->enabled)
1469                         __connman_device_enable(device);
1470                 else
1471                         __connman_device_disable(device);
1472
1473                 goto done;
1474         }
1475
1476         if (technology->enable_persistent &&
1477                                         !global_offlinemode) {
1478                 int err = __connman_device_enable(device);
1479                 /*
1480                  * connman_technology_add_device() calls __connman_device_enable()
1481                  * but since the device is already enabled, the call does not
1482                  * propagate through to connman_technology_enabled via
1483                  * connman_device_set_powered.
1484                  */
1485                 if (err == -EALREADY)
1486                         __connman_technology_enabled(type);
1487         }
1488         /* if technology persistent state is offline */
1489         if (!technology->enable_persistent)
1490                 __connman_device_disable(device);
1491
1492 done:
1493         technology->device_list = g_slist_prepend(technology->device_list,
1494                                                                 device);
1495
1496         return 0;
1497 }
1498
1499 int __connman_technology_remove_device(struct connman_device *device)
1500 {
1501         struct connman_technology *technology;
1502         enum connman_service_type type;
1503
1504         DBG("device %p", device);
1505
1506         type = __connman_device_get_service_type(device);
1507
1508         technology = technology_find(type);
1509         if (!technology) {
1510                 techless_device_list = g_slist_remove(techless_device_list,
1511                                                                 device);
1512                 return -ENXIO;
1513         }
1514
1515         technology->device_list = g_slist_remove(technology->device_list,
1516                                                                 device);
1517
1518         if (technology->tethering)
1519                 set_tethering(technology, false);
1520
1521         technology_put(technology);
1522
1523         return 0;
1524 }
1525
1526 int __connman_technology_enabled(enum connman_service_type type)
1527 {
1528         struct connman_technology *technology;
1529
1530         technology = technology_find(type);
1531         if (!technology)
1532                 return -ENXIO;
1533
1534         DBG("technology %p type %s rfkill %d enabled %d", technology,
1535                 get_name(type), technology->rfkill_driven,
1536                 technology->enabled);
1537
1538         if (technology->rfkill_driven) {
1539                 if (technology->tethering_persistent)
1540                         enable_tethering(technology);
1541                 return 0;
1542         }
1543
1544         return technology_enabled(technology);
1545 }
1546
1547 int __connman_technology_disabled(enum connman_service_type type)
1548 {
1549         struct connman_technology *technology;
1550         GSList *list;
1551
1552         technology = technology_find(type);
1553         if (!technology)
1554                 return -ENXIO;
1555
1556         if (technology->rfkill_driven)
1557                 return 0;
1558
1559         for (list = technology->device_list; list; list = list->next) {
1560                 struct connman_device *device = list->data;
1561
1562                 if (connman_device_get_powered(device))
1563                         return 0;
1564         }
1565
1566         return technology_disabled(technology);
1567 }
1568
1569 int __connman_technology_set_offlinemode(bool offlinemode)
1570 {
1571         GSList *list;
1572         int err = -EINVAL, enabled_tech_count = 0;
1573
1574         if (global_offlinemode == offlinemode)
1575                 return 0;
1576
1577         DBG("offlinemode %s", offlinemode ? "On" : "Off");
1578
1579         /*
1580          * This is a bit tricky. When you set offlinemode, there is no
1581          * way to differentiate between attempting offline mode and
1582          * resuming offlinemode from last saved profile. We need that
1583          * information in rfkill_update, otherwise it falls back on the
1584          * technology's persistent state. Hence we set the offline mode here
1585          * but save it & call the notifier only if it is successful.
1586          */
1587
1588         global_offlinemode = offlinemode;
1589
1590         /* Traverse technology list, enable/disable each technology. */
1591         for (list = technology_list; list; list = list->next) {
1592                 struct connman_technology *technology = list->data;
1593
1594                 if (offlinemode)
1595                         err = technology_disable(technology);
1596                 else {
1597                         if (technology->hardblocked)
1598                                 continue;
1599
1600                         if (technology->enable_persistent) {
1601                                 err = technology_enable(technology);
1602                                 enabled_tech_count++;
1603                         }
1604                 }
1605         }
1606
1607         if (err == 0 || err == -EINPROGRESS || err == -EALREADY ||
1608                         (err == -EINVAL && enabled_tech_count == 0)) {
1609                 connman_technology_save_offlinemode();
1610                 __connman_notifier_offlinemode(offlinemode);
1611         } else
1612                 global_offlinemode = connman_technology_load_offlinemode();
1613
1614         return err;
1615 }
1616
1617 void __connman_technology_set_connected(enum connman_service_type type,
1618                 bool connected)
1619 {
1620         struct connman_technology *technology;
1621         dbus_bool_t val;
1622
1623         technology = technology_find(type);
1624         if (!technology)
1625                 return;
1626
1627         DBG("technology %p connected %d", technology, connected);
1628
1629         technology->connected = connected;
1630
1631         val = connected;
1632         connman_dbus_property_changed_basic(technology->path,
1633                         CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
1634                         DBUS_TYPE_BOOLEAN, &val);
1635 }
1636
1637 static bool technology_apply_rfkill_change(struct connman_technology *technology,
1638                                                 bool softblock,
1639                                                 bool hardblock,
1640                                                 bool new_rfkill)
1641 {
1642         bool hardblock_changed = false;
1643         bool apply = true;
1644         GList *start, *list;
1645
1646         DBG("technology %p --> %d/%d vs %d/%d",
1647                         technology, softblock, hardblock,
1648                         technology->softblocked, technology->hardblocked);
1649
1650         if (technology->hardblocked == hardblock)
1651                 goto softblock_change;
1652
1653         if (!(new_rfkill && !hardblock)) {
1654                 start = g_hash_table_get_values(rfkill_list);
1655
1656                 for (list = start; list; list = list->next) {
1657                         struct connman_rfkill *rfkill = list->data;
1658
1659                         if (rfkill->type != technology->type)
1660                                 continue;
1661
1662                         if (rfkill->hardblock != hardblock)
1663                                 apply = false;
1664                 }
1665
1666                 g_list_free(start);
1667         }
1668
1669         if (!apply)
1670                 goto softblock_change;
1671
1672         technology->hardblocked = hardblock;
1673         hardblock_changed = true;
1674
1675 softblock_change:
1676         if (!apply && technology->softblocked != softblock)
1677                 apply = true;
1678
1679         if (!apply)
1680                 return technology->hardblocked;
1681
1682         technology->softblocked = softblock;
1683
1684         if (technology->hardblocked ||
1685                                         technology->softblocked) {
1686                 if (technology_disabled(technology) != -EALREADY)
1687                         technology_affect_devices(technology, false);
1688         } else if (!technology->hardblocked &&
1689                                         !technology->softblocked) {
1690                 if (technology_enabled(technology) != -EALREADY)
1691                         technology_affect_devices(technology, true);
1692         }
1693
1694         if (hardblock_changed) {
1695                 if (technology->hardblocked) {
1696                         DBG("%s is switched off.", get_name(technology->type));
1697                         technology_dbus_unregister(technology);
1698                 } else {
1699                         DBG("%s is switched on.", get_name(technology->type));
1700                         technology_dbus_register(technology);
1701
1702                         if (global_offlinemode)
1703                                 __connman_rfkill_block(technology->type, true);
1704                 }
1705         }
1706
1707         return technology->hardblocked;
1708 }
1709
1710 int __connman_technology_add_rfkill(unsigned int index,
1711                                         enum connman_service_type type,
1712                                                 bool softblock,
1713                                                 bool hardblock)
1714 {
1715         struct connman_technology *technology;
1716         struct connman_rfkill *rfkill;
1717
1718         DBG("index %u type %d soft %u hard %u", index, type,
1719                                                         softblock, hardblock);
1720
1721         rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1722         if (rfkill)
1723                 goto done;
1724
1725         rfkill = g_try_new0(struct connman_rfkill, 1);
1726         if (!rfkill)
1727                 return -ENOMEM;
1728
1729         rfkill->index = index;
1730         rfkill->type = type;
1731         rfkill->softblock = softblock;
1732         rfkill->hardblock = hardblock;
1733
1734         g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
1735
1736 done:
1737         technology = technology_get(type);
1738         /* If there is no driver for this type, ignore it. */
1739         if (!technology)
1740                 return -ENXIO;
1741
1742         technology->rfkill_driven = true;
1743
1744         /* If hardblocked, there is no need to handle softblocked state */
1745         if (technology_apply_rfkill_change(technology,
1746                                 softblock, hardblock, true))
1747                 return 0;
1748
1749         if (global_offlinemode)
1750                 return 0;
1751
1752         /*
1753          * Depending on softblocked state we unblock/block according to
1754          * offlinemode and persistente state.
1755          */
1756         if (technology->softblocked &&
1757                                 technology->enable_persistent)
1758                 return __connman_rfkill_block(type, false);
1759         else if (!technology->softblocked &&
1760                                 !technology->enable_persistent)
1761                 return __connman_rfkill_block(type, true);
1762
1763         return 0;
1764 }
1765
1766 int __connman_technology_update_rfkill(unsigned int index,
1767                                         enum connman_service_type type,
1768                                                 bool softblock,
1769                                                 bool hardblock)
1770 {
1771         struct connman_technology *technology;
1772         struct connman_rfkill *rfkill;
1773
1774         DBG("index %u soft %u hard %u", index, softblock, hardblock);
1775
1776         rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1777         if (!rfkill)
1778                 return -ENXIO;
1779
1780         if (rfkill->softblock == softblock &&
1781                                 rfkill->hardblock == hardblock)
1782                 return 0;
1783
1784         rfkill->softblock = softblock;
1785         rfkill->hardblock = hardblock;
1786
1787         technology = technology_find(type);
1788         /* If there is no driver for this type, ignore it. */
1789         if (!technology)
1790                 return -ENXIO;
1791
1792         technology_apply_rfkill_change(technology, softblock, hardblock,
1793                                                                 false);
1794
1795         if (technology->hardblocked)
1796                 DBG("%s hardblocked", get_name(technology->type));
1797         else
1798                 DBG("%s is%s softblocked", get_name(technology->type),
1799                         technology->softblocked ? "" : " not");
1800
1801         return 0;
1802 }
1803
1804 int __connman_technology_remove_rfkill(unsigned int index,
1805                                         enum connman_service_type type)
1806 {
1807         struct connman_technology *technology;
1808         struct connman_rfkill *rfkill;
1809
1810         DBG("index %u", index);
1811
1812         rfkill = g_hash_table_lookup(rfkill_list, GINT_TO_POINTER(index));
1813         if (!rfkill)
1814                 return -ENXIO;
1815
1816         g_hash_table_remove(rfkill_list, GINT_TO_POINTER(index));
1817
1818         technology = technology_find(type);
1819         if (!technology)
1820                 return -ENXIO;
1821
1822         technology_apply_rfkill_change(technology,
1823                 technology->softblocked, !technology->hardblocked, false);
1824
1825         technology_put(technology);
1826
1827         return 0;
1828 }
1829
1830 int __connman_technology_init(void)
1831 {
1832         DBG("");
1833
1834         connection = connman_dbus_get_connection();
1835
1836         rfkill_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1837                                                         NULL, free_rfkill);
1838
1839         global_offlinemode = connman_technology_load_offlinemode();
1840
1841         /* This will create settings file if it is missing */
1842         connman_technology_save_offlinemode();
1843
1844         return 0;
1845 }
1846
1847 void __connman_technology_cleanup(void)
1848 {
1849         DBG("");
1850
1851         while (technology_list) {
1852                 struct connman_technology *technology = technology_list->data;
1853                 technology_list = g_slist_remove(technology_list, technology);
1854                 technology_put(technology);
1855         }
1856
1857         g_hash_table_destroy(rfkill_list);
1858
1859         dbus_connection_unref(connection);
1860 }