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