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