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