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