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