2 * Network Configuration Module
4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include <dbus/dbus-glib-lowlevel.h>
25 #include <vconf-keys.h>
32 #include "wifi-agent.h"
33 #include "wifi-power.h"
34 #include "wifi-state.h"
35 #include "netsupplicant.h"
36 #include "network-state.h"
37 #include "cellular-state.h"
38 #include "signal-handler.h"
39 #include "wifi-ssid-scan.h"
40 #include "wifi-background-scan.h"
42 #define SIGNAL_INTERFACE_REMOVED "InterfaceRemoved"
43 #define SIGNAL_SCAN_DONE "ScanDone"
44 #define SIGNAL_BSS_ADDED "BSSAdded"
45 #define SIGNAL_PROPERTIES_CHANGED "PropertiesChanged"
46 #define SIGNAL_PROPERTIES_DRIVER_HANGED "DriverHanged"
48 #define CONNMAN_SIGNAL_SERVICES_CHANGED "ServicesChanged"
49 #define CONNMAN_SIGNAL_PROPERTY_CHANGED "PropertyChanged"
51 #define CONNMAN_TECHNOLOGY_SIGNAL_FILTER \
52 "type='signal',interface='"CONNMAN_TECHNOLOGY_INTERFACE"'"
54 #define CONNMAN_SERVICE_STATE_SIGNAL_FILTER \
55 "type='signal',interface='"CONNMAN_SERVICE_INTERFACE \
56 "',member='PropertyChanged',arg0='State'"
58 #define CONNMAN_SERVICE_PROXY_SIGNAL_FILTER \
59 "type='signal',interface='"CONNMAN_SERVICE_INTERFACE \
60 "',member='PropertyChanged',arg0='Proxy'"
62 #define SUPPLICANT_INTERFACE_REMOVED_SIGNAL_FILTER \
63 "type='signal',interface='"SUPPLICANT_INTERFACE \
64 "',member='"SIGNAL_INTERFACE_REMOVED"'"
66 #define SUPPLICANT_INTERFACE_PROPERTIESCHANGED_SIGNAL_FILTER \
67 "type='signal',interface='"SUPPLICANT_IFACE_INTERFACE \
68 "',member='"SIGNAL_PROPERTIES_CHANGED"'"
70 #define SUPPLICANT_INTERFACE_BSSADDED_SIGNAL_FILTER \
71 "type='signal',interface='"SUPPLICANT_IFACE_INTERFACE \
72 "',member='"SIGNAL_BSS_ADDED"'"
74 #define SUPPLICANT_INTERFACE_SCANDONE_SIGNAL_FILTER \
75 "type='signal',interface='"SUPPLICANT_IFACE_INTERFACE \
76 "',member='"SIGNAL_SCAN_DONE"'"
78 #define SUPPLICANT_INTERFACE_DRIVERHANGED_SIGNAL_FILTER \
79 "type='signal',interface='"SUPPLICANT_IFACE_INTERFACE \
80 "',member='"SIGNAL_PROPERTIES_DRIVER_HANGED"'"
82 #define CONNMAN_SERVICE_NAMECHANGED_SIGNAL_FILTER \
83 "type='signal',sender='"DBUS_SERVICE_DBUS \
84 "',interface='"DBUS_INTERFACE_DBUS \
85 "',member='NameOwnerChanged',path='/org/freedesktop/DBus'" \
86 ",arg0='"CONNMAN_SERVICE"'"
89 static DBusConnection *signal_connection = NULL;
91 static void __netconfig_technology_signal_handler(DBusMessage *msg)
94 const char *tech = NULL;
95 dbus_bool_t value = FALSE;
97 if (netconfig_dbus_get_basic_params_string(msg,
98 &key, DBUS_TYPE_BOOLEAN, &value) != TRUE)
101 tech = dbus_message_get_path(msg);
102 if (key == NULL || tech == NULL)
105 if (g_str_has_prefix(tech, CONNMAN_WIFI_TECHNOLOGY_PREFIX) == TRUE) {
106 if (g_strcmp0(key, "Powered") == 0) {
109 netconfig_wifi_update_power_state(TRUE);
111 netconfig_wifi_update_power_state(FALSE);
113 } else if (g_strcmp0(key, "Connected") == 0) {
114 /* Connection state */
115 netconfig_wifi_state_set_technology_state(
116 NETCONFIG_WIFI_TECH_CONNECTED);
117 } else if (g_strcmp0(key, "Tethering") == 0) {
118 /* Tethering state */
119 netconfig_wifi_state_set_technology_state(
120 NETCONFIG_WIFI_TECH_TETHERED);
122 } else if (g_str_has_prefix(tech,
123 CONNMAN_CELLULAR_TECHNOLOGY_PREFIX) == TRUE) {
124 /* Cellular technology state */
128 static void __netconfig_service_signal_handler(DBusMessage *msg)
130 char *sigvalue = NULL;
131 char *property = NULL;
132 char *service_profile = NULL;
133 DBusMessageIter args, variant, iter1, iter2, iter3, iter4;
134 const char *value = NULL;
136 service_profile = (char *)dbus_message_get_path(msg);
137 if (service_profile == NULL)
140 dbus_message_iter_init(msg, &args);
141 dbus_message_iter_get_basic(&args, &sigvalue);
142 if (sigvalue == NULL)
145 if (g_str_equal(sigvalue, "State") == TRUE) {
146 dbus_message_iter_next(&args);
147 dbus_message_iter_recurse(&args, &variant);
148 dbus_message_iter_get_basic(&variant, &property);
150 DBG("[%s] %s", property, service_profile);
151 if (netconfig_is_wifi_profile(service_profile) == TRUE) {
154 vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
155 if (wifi_state == VCONFKEY_WIFI_OFF)
158 if (g_str_equal(property, "ready") == TRUE ||
159 g_str_equal(property, "online") == TRUE) {
160 if (wifi_state >= VCONFKEY_WIFI_CONNECTED)
163 netconfig_update_default_profile(service_profile);
165 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTED);
167 } else if (g_str_equal(property, "failure") == TRUE ||
168 g_str_equal(property, "disconnect") == TRUE ||
169 g_str_equal(property, "idle") == TRUE) {
170 if (netconfig_get_default_profile() == NULL ||
171 netconfig_is_wifi_profile(netconfig_get_default_profile())
173 if (g_str_equal(property, "failure") == TRUE)
174 netconfig_wifi_state_set_service_state(
175 NETCONFIG_WIFI_FAILURE);
177 netconfig_wifi_state_set_service_state(
178 NETCONFIG_WIFI_IDLE);
182 if (g_str_equal(service_profile, netconfig_get_default_profile())
186 netconfig_update_default_profile(NULL);
188 if (g_str_equal(property, "failure") == TRUE)
189 netconfig_wifi_state_set_service_state(
190 NETCONFIG_WIFI_FAILURE);
192 netconfig_wifi_state_set_service_state(
193 NETCONFIG_WIFI_IDLE);
195 } else if (g_str_equal(property, "association") == TRUE ||
196 g_str_equal(property, "configuration") == TRUE) {
197 if (netconfig_get_default_profile() == NULL ||
198 netconfig_is_wifi_profile(netconfig_get_default_profile())
200 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTING);
204 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
207 netconfig_update_default_profile(NULL);
209 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTING);
213 if (g_str_equal(property, "ready") == TRUE ||
214 g_str_equal(property, "online") == TRUE) {
215 if (netconfig_get_default_profile() == NULL)
216 netconfig_update_default_profile(service_profile);
218 if (netconfig_is_cellular_profile(service_profile) == TRUE)
219 netconfig_cellular_state_set_service_state(NETCONFIG_CELLULAR_ONLINE);
220 } else if (g_str_equal(property, "failure") == TRUE ||
221 g_str_equal(property, "disconnect") == TRUE ||
222 g_str_equal(property, "idle") == TRUE) {
223 if (netconfig_get_default_profile() == NULL)
226 if (netconfig_is_cellular_profile(service_profile) == TRUE)
227 netconfig_cellular_state_set_service_state(NETCONFIG_CELLULAR_IDLE);
229 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
232 netconfig_update_default_profile(NULL);
233 } else if (g_str_equal(property, "association") == TRUE ||
234 g_str_equal(property, "configuration") == TRUE) {
235 if (netconfig_get_default_profile() == NULL)
238 if (netconfig_is_cellular_profile(service_profile) == TRUE)
239 netconfig_cellular_state_set_service_state(NETCONFIG_CELLULAR_IDLE);
241 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
244 netconfig_update_default_profile(NULL);
247 } else if (g_str_equal(sigvalue, "Proxy") == TRUE) {
248 dbus_message_iter_next(&args);
249 dbus_message_iter_recurse(&args, &variant);
251 if (netconfig_is_wifi_profile(service_profile) != TRUE ||
252 g_strcmp0(service_profile, netconfig_get_default_profile()) != 0)
255 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
258 dbus_message_iter_recurse(&variant, &iter1);
259 while (dbus_message_iter_get_arg_type(&iter1) ==
260 DBUS_TYPE_DICT_ENTRY) {
261 dbus_message_iter_recurse(&iter1, &iter2);
262 dbus_message_iter_get_basic(&iter2, &property);
264 if (g_strcmp0(property, "Servers") == 0) {
265 dbus_message_iter_next(&iter2);
266 dbus_message_iter_recurse(&iter2, &iter3);
268 if (dbus_message_iter_get_arg_type(&iter3) !=
272 dbus_message_iter_recurse(&iter3, &iter4);
273 if (dbus_message_iter_get_arg_type(&iter4) !=
277 dbus_message_iter_get_basic(&iter4, &value);
278 DBG("Proxy - [%s]", value);
280 vconf_set_str(VCONFKEY_NETWORK_PROXY, value);
282 } else if (g_strcmp0(property, "Method") == 0) {
283 dbus_message_iter_next(&iter2);
284 dbus_message_iter_recurse(&iter2, &iter3);
286 if (dbus_message_iter_get_arg_type(&iter3) !=
290 dbus_message_iter_get_basic(&iter3, &value);
291 DBG("Method - [%s]", value);
293 if (g_strcmp0(value, "direct") == 0)
294 vconf_set_str(VCONFKEY_NETWORK_PROXY, "");
298 dbus_message_iter_next(&iter1);
303 static void __netconfig_dbus_name_changed_signal_handler(DBusMessage *msg)
305 char *name, *old, *new;
307 dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
308 DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new);
310 if (g_strcmp0(name, CONNMAN_SERVICE) == 0 && *new == '\0') {
311 DBG("ConnMan destroyed: name %s, old %s, new %s", name, old, new);
313 netconfig_agent_register();
317 static DBusHandlerResult __netconfig_signal_filter_handler(
318 DBusConnection *conn, DBusMessage *msg, void *user_data)
321 DBG("Invalid Message. Ignore");
322 return DBUS_HANDLER_RESULT_HANDLED;
325 if (dbus_message_is_signal(msg, CONNMAN_TECHNOLOGY_INTERFACE,
326 CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
327 __netconfig_technology_signal_handler(msg);
329 return DBUS_HANDLER_RESULT_HANDLED;
330 } else if (dbus_message_is_signal(msg, CONNMAN_SERVICE_INTERFACE,
331 CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
332 __netconfig_service_signal_handler(msg);
334 return DBUS_HANDLER_RESULT_HANDLED;
335 } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE,
336 SIGNAL_INTERFACE_REMOVED)) {
337 if (netconfig_wifi_is_wps_enabled() == TRUE)
338 netconfig_wifi_wps_signal_scanaborted();
340 return DBUS_HANDLER_RESULT_HANDLED;
341 } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
342 SIGNAL_PROPERTIES_CHANGED)) {
343 dbus_bool_t scanning = FALSE;
344 void *property = &scanning;
346 if (netconfig_dbus_get_basic_params_array(msg,
347 "Scanning", &property) == TRUE) {
348 if (scanning == TRUE)
349 netconfig_wifi_set_scanning(TRUE);
352 return DBUS_HANDLER_RESULT_HANDLED;
353 } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
355 if (netconfig_wifi_get_ssid_scan_state() == TRUE)
356 netconfig_wifi_bss_added(msg);
358 netconfig_wifi_set_bss_found(TRUE);
360 return DBUS_HANDLER_RESULT_HANDLED;
361 } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
363 netconfig_wifi_set_scanning(FALSE);
365 if (netconfig_wifi_is_wps_enabled() == TRUE) {
366 netconfig_wifi_wps_signal_scandone();
367 if (netconfig_wifi_state_get_technology_state() <
368 NETCONFIG_WIFI_TECH_POWERED)
369 return DBUS_HANDLER_RESULT_HANDLED;
372 if (netconfig_wifi_get_bgscan_state() != TRUE) {
373 if (netconfig_wifi_get_ssid_scan_state() == TRUE)
374 netconfig_wifi_notify_ssid_scan_done();
376 netconfig_wifi_ssid_scan(NULL);
378 netconfig_wifi_check_network_notification();
381 return DBUS_HANDLER_RESULT_HANDLED;
382 } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
383 SIGNAL_PROPERTIES_DRIVER_HANGED)) {
384 ERR("Critical. Wi-Fi firmware crashed");
386 netconfig_wifi_recover_firmware();
388 return DBUS_HANDLER_RESULT_HANDLED;
389 } else if (dbus_message_is_signal(msg, DBUS_INTERFACE_DBUS,
390 "NameOwnerChanged")) {
391 __netconfig_dbus_name_changed_signal_handler(msg);
393 return DBUS_HANDLER_RESULT_HANDLED;
396 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
399 void netconfig_register_signal(void)
402 DBusConnection *conn = NULL;
404 dbus_error_init(&err);
405 conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
407 ERR("Failed to get system bus [%s]", err.message);
408 dbus_error_free(&err);
412 signal_connection = conn;
414 dbus_connection_setup_with_g_main(conn, NULL);
416 /* listening to messages from all objects as no path is specified */
417 /* see signals from the given interface */
418 dbus_bus_add_match(conn, CONNMAN_TECHNOLOGY_SIGNAL_FILTER, &err);
419 dbus_connection_flush(conn);
420 if (dbus_error_is_set(&err)) {
421 ERR("Match error (%s)", err.message);
422 dbus_error_free(&err);
426 dbus_bus_add_match(conn, CONNMAN_SERVICE_STATE_SIGNAL_FILTER, &err);
427 dbus_connection_flush(conn);
428 if (dbus_error_is_set(&err)) {
429 ERR("Match error (%s)", err.message);
430 dbus_error_free(&err);
434 dbus_bus_add_match(conn, CONNMAN_SERVICE_PROXY_SIGNAL_FILTER, &err);
435 dbus_connection_flush(conn);
436 if (dbus_error_is_set(&err)) {
437 ERR("Match error (%s)", err.message);
438 dbus_error_free(&err);
442 dbus_bus_add_match(conn, SUPPLICANT_INTERFACE_REMOVED_SIGNAL_FILTER, &err);
443 dbus_connection_flush(conn);
444 if (dbus_error_is_set(&err)) {
445 ERR("Match error (%s)", err.message);
446 dbus_error_free(&err);
450 dbus_bus_add_match(conn,
451 SUPPLICANT_INTERFACE_PROPERTIESCHANGED_SIGNAL_FILTER, &err);
452 dbus_connection_flush(conn);
453 if (dbus_error_is_set(&err)) {
454 ERR("Match error (%s)", err.message);
455 dbus_error_free(&err);
459 dbus_bus_add_match(conn, SUPPLICANT_INTERFACE_BSSADDED_SIGNAL_FILTER, &err);
460 dbus_connection_flush(conn);
461 if (dbus_error_is_set(&err)) {
462 ERR("Match error (%s)", err.message);
463 dbus_error_free(&err);
467 dbus_bus_add_match(conn, SUPPLICANT_INTERFACE_SCANDONE_SIGNAL_FILTER, &err);
468 dbus_connection_flush(conn);
469 if (dbus_error_is_set(&err)) {
470 ERR("Match error (%s)", err.message);
471 dbus_error_free(&err);
475 dbus_bus_add_match(conn,
476 SUPPLICANT_INTERFACE_DRIVERHANGED_SIGNAL_FILTER, &err);
477 dbus_connection_flush(conn);
478 if (dbus_error_is_set(&err)) {
479 ERR("Match error (%s)", err.message);
480 dbus_error_free(&err);
484 dbus_bus_add_match(conn, CONNMAN_SERVICE_NAMECHANGED_SIGNAL_FILTER, &err);
485 dbus_connection_flush(conn);
486 if (dbus_error_is_set(&err)) {
487 ERR("Match error (%s)", err.message);
488 dbus_error_free(&err);
492 if (dbus_connection_add_filter(conn,
493 __netconfig_signal_filter_handler, NULL, NULL) == FALSE) {
494 ERR("Error! dbus_connection_add_filter() failed");
498 INFO("Successfully register DBus signal filters");
500 /* In case ConnMan precedes this signal register,
501 * net-config should update the default connected profile.
503 netconfig_update_default();
506 void netconfig_deregister_signal(void)
508 if (signal_connection == NULL) {
509 ERR("Already de-registered. Nothing to be done");
513 dbus_connection_remove_filter(signal_connection,
514 __netconfig_signal_filter_handler, NULL);
515 INFO("Successfully remove DBus signal filters");
517 dbus_connection_unref(signal_connection);
518 signal_connection = NULL;