15 */ 16 17#include "utils/includes.h" 18#include <dbus/dbus.h> 19 20#include "utils/common.h" 21#include "utils/eloop.h" 22#include "dbus_common.h" 23#include "dbus_common_i.h" 24#include "dbus_new.h" 25#include "dbus_old.h" 26 27 28#ifndef SIGPOLL 29#ifdef SIGIO 30/* 31 * If we do not have SIGPOLL, try to use SIGIO instead. This is needed for 32 * FreeBSD. 33 */ 34#define SIGPOLL SIGIO 35#endif 36#endif 37 38 39static void dispatch_data(DBusConnection *con) 40{ 41 while (dbus_connection_get_dispatch_status(con) == 42 DBUS_DISPATCH_DATA_REMAINS) 43 dbus_connection_dispatch(con); 44} 45 46 47/** 48 * dispatch_initial_dbus_messages - Dispatch initial dbus messages after 49 * claiming bus name 50 * @eloop_ctx: the DBusConnection to dispatch on 51 * @timeout_ctx: unused 52 * 53 * If clients are quick to notice that service claimed its bus name, 54 * there may have been messages that came in before initialization was 55 * all finished. Dispatch those here. 56 */ 57static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx) 58{ 59 DBusConnection *con = eloop_ctx; 60 dispatch_data(con); 61} 62 63 64static void process_watch(struct wpas_dbus_priv *priv, 65 DBusWatch *watch, eloop_event_type type) 66{ 67 dbus_connection_ref(priv->con); 68 69 priv->should_dispatch = 0; 70 71 if (type == EVENT_TYPE_READ) 72 dbus_watch_handle(watch, DBUS_WATCH_READABLE); 73 else if (type == EVENT_TYPE_WRITE) 74 dbus_watch_handle(watch, DBUS_WATCH_WRITABLE); 75 else if (type == EVENT_TYPE_EXCEPTION) 76 dbus_watch_handle(watch, DBUS_WATCH_ERROR); 77 78 if (priv->should_dispatch) { 79 dispatch_data(priv->con); 80 priv->should_dispatch = 0; 81 } 82 83 dbus_connection_unref(priv->con); 84} 85 86 87static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx) 88{ 89 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION); 90} 91 92 93static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx) 94{ 95 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ); 96} 97 98 99static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx) 100{ 101 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE); 102} 103 104 105static dbus_bool_t add_watch(DBusWatch *watch, void *data) 106{ 107 struct wpas_dbus_priv *priv = data; 108 unsigned int flags; 109 int fd; 110 111 if (!dbus_watch_get_enabled(watch)) 112 return TRUE; 113 114 flags = dbus_watch_get_flags(watch); 115 fd = dbus_watch_get_unix_fd(watch); 116 117 eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception, 118 priv, watch); 119 120 if (flags & DBUS_WATCH_READABLE) { 121 eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read, 122 priv, watch); 123 } 124 if (flags & DBUS_WATCH_WRITABLE) { 125 eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write, 126 priv, watch); 127 } 128 129 dbus_watch_set_data(watch, priv, NULL); 130 131 return TRUE; 132} 133 134 135static void remove_watch(DBusWatch *watch, void *data) 136{ 137 unsigned int flags; 138 int fd; 139 140 flags = dbus_watch_get_flags(watch); 141 fd = dbus_watch_get_unix_fd(watch); 142 143 eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION); 144 145 if (flags & DBUS_WATCH_READABLE) 146 eloop_unregister_sock(fd, EVENT_TYPE_READ); 147 if (flags & DBUS_WATCH_WRITABLE) 148 eloop_unregister_sock(fd, EVENT_TYPE_WRITE); 149 150 dbus_watch_set_data(watch, NULL, NULL); 151} 152 153 154static void watch_toggled(DBusWatch *watch, void *data) 155{ 156 if (dbus_watch_get_enabled(watch)) 157 add_watch(watch, data); 158 else 159 remove_watch(watch, data); 160} 161 162 163static void process_timeout(void *eloop_ctx, void *sock_ctx) 164{ 165 DBusTimeout *timeout = sock_ctx; 166 dbus_timeout_handle(timeout); 167} 168 169 170static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) 171{ 172 struct wpas_dbus_priv *priv = data; 173 if (!dbus_timeout_get_enabled(timeout)) 174 return TRUE; 175 176 eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000, 177 process_timeout, priv, timeout); 178 179 dbus_timeout_set_data(timeout, priv, NULL); 180 181 return TRUE; 182} 183 184 185static void remove_timeout(DBusTimeout *timeout, void *data) 186{ 187 struct wpas_dbus_priv *priv = data; 188 eloop_cancel_timeout(process_timeout, priv, timeout); 189 dbus_timeout_set_data(timeout, NULL, NULL); 190} 191 192 193static void timeout_toggled(DBusTimeout *timeout, void *data) 194{ 195 if (dbus_timeout_get_enabled(timeout)) 196 add_timeout(timeout, data); 197 else 198 remove_timeout(timeout, data); 199} 200 201 202static void process_wakeup_main(int sig, void *signal_ctx) 203{ 204 struct wpas_dbus_priv *priv = signal_ctx; 205 206 if (sig != SIGPOLL || !priv->con) 207 return; 208 209 if (dbus_connection_get_dispatch_status(priv->con) != 210 DBUS_DISPATCH_DATA_REMAINS) 211 return; 212 213 /* Only dispatch once - we do not want to starve other events */ 214 dbus_connection_ref(priv->con); 215 dbus_connection_dispatch(priv->con); 216 dbus_connection_unref(priv->con); 217} 218 219 220/** 221 * wakeup_main - Attempt to wake our mainloop up 222 * @data: dbus control interface private data 223 * 224 * Try to wake up the main eloop so it will process 225 * dbus events that may have happened. 226 */ 227static void wakeup_main(void *data) 228{ 229 struct wpas_dbus_priv *priv = data; 230 231 /* Use SIGPOLL to break out of the eloop select() */ 232 raise(SIGPOLL); 233 priv->should_dispatch = 1; 234} 235 236 237/** 238 * integrate_with_eloop - Register our mainloop integration with dbus 239 * @connection: connection to the system message bus 240 * @priv: a dbus control interface data structure 241 * Returns: 0 on success, -1 on failure 242 */ 243static int integrate_with_eloop(struct wpas_dbus_priv *priv) 244{ 245 if (!dbus_connection_set_watch_functions(priv->con, add_watch, 246 remove_watch, watch_toggled, 247 priv, NULL) || 248 !dbus_connection_set_timeout_functions(priv->con, add_timeout, 249 remove_timeout, 250 timeout_toggled, priv, 251 NULL)) { 252 wpa_printf(MSG_ERROR, "dbus: Failed to set callback " 253 "functions"); 254 return -1; 255 } 256 257 if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv)) 258 return -1; 259 dbus_connection_set_wakeup_main_function(priv->con, wakeup_main, 260 priv, NULL); 261 262 return 0; 263} 264 265 266static int wpas_dbus_init_common(struct wpas_dbus_priv *priv) 267{ 268 DBusError error; 269 int ret = 0; 270 271 /* Get a reference to the system bus */ 272 dbus_error_init(&error); 273 priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error); 274 if (!priv->con) { 275 wpa_printf(MSG_ERROR, "dbus: Could not acquire the system " 276 "bus: %s - %s", error.name, error.message); 277 ret = -1; 278 } 279 dbus_error_free(&error); 280 281 return ret; 282} 283 284 285static int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv) 286{ 287 /* Tell dbus about our mainloop integration functions */ 288 integrate_with_eloop(priv); 289 290 /* 291 * Dispatch initial DBus messages that may have come in since the bus 292 * name was claimed above. Happens when clients are quick to notice the 293 * service. 294 * 295 * FIXME: is there a better solution to this problem? 296 */ 297 eloop_register_timeout(0, 50, dispatch_initial_dbus_messages, 298 priv->con, NULL); 299 300 return 0; 301} 302 303 304static void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv) 305{ 306 if (priv->con) { 307 eloop_cancel_timeout(dispatch_initial_dbus_messages, 308 priv->con, NULL); 309 dbus_connection_set_watch_functions(priv->con, NULL, NULL, 310 NULL, NULL, NULL); 311 dbus_connection_set_timeout_functions(priv->con, NULL, NULL, 312 NULL, NULL, NULL); 313 dbus_connection_unref(priv->con); 314 } 315 316 os_free(priv); 317} 318 319 320struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global) 321{ 322 struct wpas_dbus_priv *priv; 323 324 priv = os_zalloc(sizeof(*priv)); 325 if (priv == NULL) 326 return NULL; 327 priv->global = global; 328 329 if (wpas_dbus_init_common(priv) < 0) { 330 wpas_dbus_deinit(priv); 331 return NULL; 332 } 333 334#ifdef CONFIG_CTRL_IFACE_DBUS_NEW 335 if (wpas_dbus_ctrl_iface_init(priv) < 0) { 336 wpas_dbus_deinit(priv); 337 return NULL; 338 } 339#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ 340 341#ifdef CONFIG_CTRL_IFACE_DBUS 342 if (wpa_supplicant_dbus_ctrl_iface_init(priv) < 0) { 343 wpas_dbus_deinit(priv); 344 return NULL; 345 } 346#endif /* CONFIG_CTRL_IFACE_DBUS */ 347 348 if (wpas_dbus_init_common_finish(priv) < 0) { 349 wpas_dbus_deinit(priv); 350 return NULL; 351 } 352 353 return priv; 354} 355 356 357void wpas_dbus_deinit(struct wpas_dbus_priv *priv) 358{ 359 if (priv == NULL) 360 return; 361 362#ifdef CONFIG_CTRL_IFACE_DBUS_NEW 363 wpas_dbus_ctrl_iface_deinit(priv); 364#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ 365 366#ifdef CONFIG_CTRL_IFACE_DBUS 367 /* TODO: is any deinit needed? */ 368#endif /* CONFIG_CTRL_IFACE_DBUS */ 369 370 wpas_dbus_deinit_common(priv); 371}
| 9 */ 10 11#include "utils/includes.h" 12#include <dbus/dbus.h> 13 14#include "utils/common.h" 15#include "utils/eloop.h" 16#include "dbus_common.h" 17#include "dbus_common_i.h" 18#include "dbus_new.h" 19#include "dbus_old.h" 20 21 22#ifndef SIGPOLL 23#ifdef SIGIO 24/* 25 * If we do not have SIGPOLL, try to use SIGIO instead. This is needed for 26 * FreeBSD. 27 */ 28#define SIGPOLL SIGIO 29#endif 30#endif 31 32 33static void dispatch_data(DBusConnection *con) 34{ 35 while (dbus_connection_get_dispatch_status(con) == 36 DBUS_DISPATCH_DATA_REMAINS) 37 dbus_connection_dispatch(con); 38} 39 40 41/** 42 * dispatch_initial_dbus_messages - Dispatch initial dbus messages after 43 * claiming bus name 44 * @eloop_ctx: the DBusConnection to dispatch on 45 * @timeout_ctx: unused 46 * 47 * If clients are quick to notice that service claimed its bus name, 48 * there may have been messages that came in before initialization was 49 * all finished. Dispatch those here. 50 */ 51static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx) 52{ 53 DBusConnection *con = eloop_ctx; 54 dispatch_data(con); 55} 56 57 58static void process_watch(struct wpas_dbus_priv *priv, 59 DBusWatch *watch, eloop_event_type type) 60{ 61 dbus_connection_ref(priv->con); 62 63 priv->should_dispatch = 0; 64 65 if (type == EVENT_TYPE_READ) 66 dbus_watch_handle(watch, DBUS_WATCH_READABLE); 67 else if (type == EVENT_TYPE_WRITE) 68 dbus_watch_handle(watch, DBUS_WATCH_WRITABLE); 69 else if (type == EVENT_TYPE_EXCEPTION) 70 dbus_watch_handle(watch, DBUS_WATCH_ERROR); 71 72 if (priv->should_dispatch) { 73 dispatch_data(priv->con); 74 priv->should_dispatch = 0; 75 } 76 77 dbus_connection_unref(priv->con); 78} 79 80 81static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx) 82{ 83 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION); 84} 85 86 87static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx) 88{ 89 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ); 90} 91 92 93static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx) 94{ 95 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE); 96} 97 98 99static dbus_bool_t add_watch(DBusWatch *watch, void *data) 100{ 101 struct wpas_dbus_priv *priv = data; 102 unsigned int flags; 103 int fd; 104 105 if (!dbus_watch_get_enabled(watch)) 106 return TRUE; 107 108 flags = dbus_watch_get_flags(watch); 109 fd = dbus_watch_get_unix_fd(watch); 110 111 eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception, 112 priv, watch); 113 114 if (flags & DBUS_WATCH_READABLE) { 115 eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read, 116 priv, watch); 117 } 118 if (flags & DBUS_WATCH_WRITABLE) { 119 eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write, 120 priv, watch); 121 } 122 123 dbus_watch_set_data(watch, priv, NULL); 124 125 return TRUE; 126} 127 128 129static void remove_watch(DBusWatch *watch, void *data) 130{ 131 unsigned int flags; 132 int fd; 133 134 flags = dbus_watch_get_flags(watch); 135 fd = dbus_watch_get_unix_fd(watch); 136 137 eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION); 138 139 if (flags & DBUS_WATCH_READABLE) 140 eloop_unregister_sock(fd, EVENT_TYPE_READ); 141 if (flags & DBUS_WATCH_WRITABLE) 142 eloop_unregister_sock(fd, EVENT_TYPE_WRITE); 143 144 dbus_watch_set_data(watch, NULL, NULL); 145} 146 147 148static void watch_toggled(DBusWatch *watch, void *data) 149{ 150 if (dbus_watch_get_enabled(watch)) 151 add_watch(watch, data); 152 else 153 remove_watch(watch, data); 154} 155 156 157static void process_timeout(void *eloop_ctx, void *sock_ctx) 158{ 159 DBusTimeout *timeout = sock_ctx; 160 dbus_timeout_handle(timeout); 161} 162 163 164static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) 165{ 166 struct wpas_dbus_priv *priv = data; 167 if (!dbus_timeout_get_enabled(timeout)) 168 return TRUE; 169 170 eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000, 171 process_timeout, priv, timeout); 172 173 dbus_timeout_set_data(timeout, priv, NULL); 174 175 return TRUE; 176} 177 178 179static void remove_timeout(DBusTimeout *timeout, void *data) 180{ 181 struct wpas_dbus_priv *priv = data; 182 eloop_cancel_timeout(process_timeout, priv, timeout); 183 dbus_timeout_set_data(timeout, NULL, NULL); 184} 185 186 187static void timeout_toggled(DBusTimeout *timeout, void *data) 188{ 189 if (dbus_timeout_get_enabled(timeout)) 190 add_timeout(timeout, data); 191 else 192 remove_timeout(timeout, data); 193} 194 195 196static void process_wakeup_main(int sig, void *signal_ctx) 197{ 198 struct wpas_dbus_priv *priv = signal_ctx; 199 200 if (sig != SIGPOLL || !priv->con) 201 return; 202 203 if (dbus_connection_get_dispatch_status(priv->con) != 204 DBUS_DISPATCH_DATA_REMAINS) 205 return; 206 207 /* Only dispatch once - we do not want to starve other events */ 208 dbus_connection_ref(priv->con); 209 dbus_connection_dispatch(priv->con); 210 dbus_connection_unref(priv->con); 211} 212 213 214/** 215 * wakeup_main - Attempt to wake our mainloop up 216 * @data: dbus control interface private data 217 * 218 * Try to wake up the main eloop so it will process 219 * dbus events that may have happened. 220 */ 221static void wakeup_main(void *data) 222{ 223 struct wpas_dbus_priv *priv = data; 224 225 /* Use SIGPOLL to break out of the eloop select() */ 226 raise(SIGPOLL); 227 priv->should_dispatch = 1; 228} 229 230 231/** 232 * integrate_with_eloop - Register our mainloop integration with dbus 233 * @connection: connection to the system message bus 234 * @priv: a dbus control interface data structure 235 * Returns: 0 on success, -1 on failure 236 */ 237static int integrate_with_eloop(struct wpas_dbus_priv *priv) 238{ 239 if (!dbus_connection_set_watch_functions(priv->con, add_watch, 240 remove_watch, watch_toggled, 241 priv, NULL) || 242 !dbus_connection_set_timeout_functions(priv->con, add_timeout, 243 remove_timeout, 244 timeout_toggled, priv, 245 NULL)) { 246 wpa_printf(MSG_ERROR, "dbus: Failed to set callback " 247 "functions"); 248 return -1; 249 } 250 251 if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv)) 252 return -1; 253 dbus_connection_set_wakeup_main_function(priv->con, wakeup_main, 254 priv, NULL); 255 256 return 0; 257} 258 259 260static int wpas_dbus_init_common(struct wpas_dbus_priv *priv) 261{ 262 DBusError error; 263 int ret = 0; 264 265 /* Get a reference to the system bus */ 266 dbus_error_init(&error); 267 priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error); 268 if (!priv->con) { 269 wpa_printf(MSG_ERROR, "dbus: Could not acquire the system " 270 "bus: %s - %s", error.name, error.message); 271 ret = -1; 272 } 273 dbus_error_free(&error); 274 275 return ret; 276} 277 278 279static int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv) 280{ 281 /* Tell dbus about our mainloop integration functions */ 282 integrate_with_eloop(priv); 283 284 /* 285 * Dispatch initial DBus messages that may have come in since the bus 286 * name was claimed above. Happens when clients are quick to notice the 287 * service. 288 * 289 * FIXME: is there a better solution to this problem? 290 */ 291 eloop_register_timeout(0, 50, dispatch_initial_dbus_messages, 292 priv->con, NULL); 293 294 return 0; 295} 296 297 298static void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv) 299{ 300 if (priv->con) { 301 eloop_cancel_timeout(dispatch_initial_dbus_messages, 302 priv->con, NULL); 303 dbus_connection_set_watch_functions(priv->con, NULL, NULL, 304 NULL, NULL, NULL); 305 dbus_connection_set_timeout_functions(priv->con, NULL, NULL, 306 NULL, NULL, NULL); 307 dbus_connection_unref(priv->con); 308 } 309 310 os_free(priv); 311} 312 313 314struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global) 315{ 316 struct wpas_dbus_priv *priv; 317 318 priv = os_zalloc(sizeof(*priv)); 319 if (priv == NULL) 320 return NULL; 321 priv->global = global; 322 323 if (wpas_dbus_init_common(priv) < 0) { 324 wpas_dbus_deinit(priv); 325 return NULL; 326 } 327 328#ifdef CONFIG_CTRL_IFACE_DBUS_NEW 329 if (wpas_dbus_ctrl_iface_init(priv) < 0) { 330 wpas_dbus_deinit(priv); 331 return NULL; 332 } 333#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ 334 335#ifdef CONFIG_CTRL_IFACE_DBUS 336 if (wpa_supplicant_dbus_ctrl_iface_init(priv) < 0) { 337 wpas_dbus_deinit(priv); 338 return NULL; 339 } 340#endif /* CONFIG_CTRL_IFACE_DBUS */ 341 342 if (wpas_dbus_init_common_finish(priv) < 0) { 343 wpas_dbus_deinit(priv); 344 return NULL; 345 } 346 347 return priv; 348} 349 350 351void wpas_dbus_deinit(struct wpas_dbus_priv *priv) 352{ 353 if (priv == NULL) 354 return; 355 356#ifdef CONFIG_CTRL_IFACE_DBUS_NEW 357 wpas_dbus_ctrl_iface_deinit(priv); 358#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ 359 360#ifdef CONFIG_CTRL_IFACE_DBUS 361 /* TODO: is any deinit needed? */ 362#endif /* CONFIG_CTRL_IFACE_DBUS */ 363 364 wpas_dbus_deinit_common(priv); 365}
|