📄 ctrl_iface_dbus.c
字号:
reply = wpas_dbus_iface_scan_results(message, wpa_s); else if (!strcmp(method, "addNetwork")) reply = wpas_dbus_iface_add_network(message, wpa_s); else if (!strcmp(method, "removeNetwork")) reply = wpas_dbus_iface_remove_network(message, wpa_s); else if (!strcmp(method, "selectNetwork")) reply = wpas_dbus_iface_select_network(message, wpa_s); else if (!strcmp(method, "capabilities")) reply = wpas_dbus_iface_capabilities(message, wpa_s); else if (!strcmp(method, "disconnect")) reply = wpas_dbus_iface_disconnect(message, wpa_s); else if (!strcmp(method, "setAPScan")) reply = wpas_dbus_iface_set_ap_scan(message, wpa_s); else if (!strcmp(method, "state")) reply = wpas_dbus_iface_get_state(message, wpa_s); else if (!strcmp(method, "setBlobs")) reply = wpas_dbus_iface_set_blobs(message, wpa_s); else if (!strcmp(method, "removeBlobs")) reply = wpas_dbus_iface_remove_blobs(message, wpa_s); } /* If the message was handled, send back the reply */ if (reply) { dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); }out: free(iface_obj_path); free(network); free(bssid); return reply ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;}/** * wpas_message_handler - dispatch incoming dbus messages * @connection: connection to the system message bus * @message: an incoming dbus message * @user_data: a pointer to a dbus control interface data structure * Returns: whether or not the message was handled * * This function dispatches all incoming dbus messages to the correct * handlers, depending on what the message's target object path is, * and what the method call is. */static DBusHandlerResult wpas_message_handler(DBusConnection *connection, DBusMessage *message, void *user_data){ struct ctrl_iface_dbus_priv *ctrl_iface = user_data; const char *method; const char *path; const char *msg_interface; DBusMessage *reply = NULL; method = dbus_message_get_member(message); path = dbus_message_get_path(message); msg_interface = dbus_message_get_interface(message); if (!method || !path || !ctrl_iface || !msg_interface) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; /* Validate the method interface */ if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; if (!strcmp(path, WPAS_DBUS_PATH)) { /* dispatch methods against our global dbus interface here */ if (!strcmp(method, "addInterface")) { reply = wpas_dbus_global_add_interface( message, ctrl_iface->global); } else if (!strcmp(method, "removeInterface")) { reply = wpas_dbus_global_remove_interface( message, ctrl_iface->global); } else if (!strcmp(method, "getInterface")) { reply = wpas_dbus_global_get_interface( message, ctrl_iface->global); } } /* If the message was handled, send back the reply */ if (reply) { dbus_connection_send(connection, reply, NULL); dbus_message_unref(reply); } return reply ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED;}/** * wpa_supplicant_dbus_notify_scan_results - Send a scan results signal * @wpa_s: %wpa_supplicant network interface data * Returns: 0 on success, -1 on failure * * Notify listeners that this interface has updated scan results. */void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s){ struct ctrl_iface_dbus_priv *iface = wpa_s->global->dbus_ctrl_iface; DBusMessage *signal; const char *path; /* Do nothing if the control interface is not turned on */ if (iface == NULL) return; path = wpa_supplicant_get_dbus_path(wpa_s); if (path == NULL) { perror("wpa_supplicant_dbus_notify_scan_results[dbus]: " "interface didn't have a dbus path"); wpa_printf(MSG_ERROR, "wpa_supplicant_dbus_notify_scan_results[dbus]: " "interface didn't have a dbus path; can't send " "scan result signal."); return; } signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE, "ScanResultsAvailable"); if (signal == NULL) { perror("wpa_supplicant_dbus_notify_scan_results[dbus]: " "couldn't create dbus signal; likely out of memory"); wpa_printf(MSG_ERROR, "dbus control interface: not enough " "memory to send scan results signal."); return; } dbus_connection_send(iface->con, signal, NULL); dbus_message_unref(signal);}/** * wpa_supplicant_dbus_notify_state_change - Send a state change signal * @wpa_s: %wpa_supplicant network interface data * @new_state: new state wpa_supplicant is entering * @old_state: old state wpa_supplicant is leaving * Returns: 0 on success, -1 on failure * * Notify listeners that wpa_supplicant has changed state */void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, wpa_states new_state, wpa_states old_state){ struct ctrl_iface_dbus_priv *iface; DBusMessage *signal = NULL; const char *path; const char *new_state_str, *old_state_str; /* Do nothing if the control interface is not turned on */ if (wpa_s->global == NULL) return; iface = wpa_s->global->dbus_ctrl_iface; if (iface == NULL) return; /* Only send signal if state really changed */ if (new_state == old_state) return; path = wpa_supplicant_get_dbus_path(wpa_s); if (path == NULL) { perror("wpa_supplicant_dbus_notify_state_change[dbus]: " "interface didn't have a dbus path"); wpa_printf(MSG_ERROR, "wpa_supplicant_dbus_notify_state_change[dbus]: " "interface didn't have a dbus path; can't send " "signal."); return; } signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE, "StateChange"); if (signal == NULL) { perror("wpa_supplicant_dbus_notify_state_change[dbus]: " "couldn't create dbus signal; likely out of memory"); wpa_printf(MSG_ERROR, "wpa_supplicant_dbus_notify_state_change[dbus]: " "couldn't create dbus signal; likely out of " "memory."); return; } new_state_str = wpa_supplicant_state_txt(new_state); old_state_str = wpa_supplicant_state_txt(old_state); if (new_state_str == NULL || old_state_str == NULL) { perror("wpa_supplicant_dbus_notify_state_change[dbus]: " "couldn't convert state strings"); wpa_printf(MSG_ERROR, "wpa_supplicant_dbus_notify_state_change[dbus]: " "couldn't convert state strings."); goto out; } if (!dbus_message_append_args(signal, DBUS_TYPE_STRING, &new_state_str, DBUS_TYPE_STRING, &old_state_str, DBUS_TYPE_INVALID)) { perror("wpa_supplicant_dbus_notify_state_change[dbus]: " "not enough memory to construct state change signal."); wpa_printf(MSG_ERROR, "wpa_supplicant_dbus_notify_state_change[dbus]: " "not enough memory to construct state change " "signal."); goto out; } dbus_connection_send(iface->con, signal, NULL);out: dbus_message_unref(signal);}/** * integrate_with_eloop - Register our mainloop integration with dbus * @connection: connection to the system message bus * @iface: a dbus control interface data structure * Returns: 0 on success, -1 on failure * * We register our mainloop integration functions with dbus here. */static int integrate_with_eloop(DBusConnection *connection, struct ctrl_iface_dbus_priv *iface){ if (!dbus_connection_set_watch_functions(connection, add_watch, remove_watch, watch_toggled, iface, NULL)) { perror("dbus_connection_set_watch_functions[dbus]"); wpa_printf(MSG_ERROR, "Not enough memory to set up dbus."); return -1; } if (!dbus_connection_set_timeout_functions(connection, add_timeout, remove_timeout, timeout_toggled, iface, NULL)) { perror("dbus_connection_set_timeout_functions[dbus]"); wpa_printf(MSG_ERROR, "Not enough memory to set up dbus."); return -1; } if (connection_setup_wakeup_main(iface) < 0) { perror("connection_setup_wakeup_main[dbus]"); wpa_printf(MSG_ERROR, "Could not setup main wakeup function."); return -1; } return 0;}/** * dispatch_initial_dbus_messages - Dispatch initial dbus messages after * claiming bus name * @eloop_ctx: the DBusConnection to dispatch on * @timeout_ctx: unused * * If clients are quick to notice that wpa_supplicant claimed its bus name, * there may have been messages that came in before initialization was * all finished. Dispatch those here. */static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx){ DBusConnection *con = eloop_ctx; while (dbus_connection_get_dispatch_status(con) == DBUS_DISPATCH_DATA_REMAINS) dbus_connection_dispatch(con);}/** * wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface * @global: Pointer to global data from wpa_supplicant_init() * Returns: Pointer to dbus_ctrl_iface date or %NULL on failure * * Initialize the dbus control interface and start receiving commands from * external programs over the bus. */struct ctrl_iface_dbus_priv *wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global){ struct ctrl_iface_dbus_priv *iface; DBusError error; int ret = -1; DBusObjectPathVTable wpas_vtable = { NULL, &wpas_message_handler, NULL, NULL, NULL, NULL }; iface = wpa_zalloc(sizeof(struct ctrl_iface_dbus_priv)); if (iface == NULL) return NULL; iface->global = global; /* Get a reference to the system bus */ dbus_error_init(&error); iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error); dbus_error_free(&error); if (!iface->con) { perror("dbus_bus_get[ctrl_iface_dbus]"); wpa_printf(MSG_ERROR, "Could not acquire the system bus."); goto fail; } /* Tell dbus about our mainloop integration functions */ if (integrate_with_eloop(iface->con, iface)) goto fail; /* Register the message handler for the global dbus interface */ if (!dbus_connection_register_object_path(iface->con, WPAS_DBUS_PATH, &wpas_vtable, iface)) { perror("dbus_connection_register_object_path[dbus]"); wpa_printf(MSG_ERROR, "Could not set up DBus message " "handler."); goto fail; } /* Register our service with the message bus */ dbus_error_init(&error); switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE, 0, &error)) { case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: ret = 0; break; case DBUS_REQUEST_NAME_REPLY_EXISTS: case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: perror("dbus_bus_request_name[dbus]"); wpa_printf(MSG_ERROR, "Could not request DBus service name: " "already registered."); break; default: perror("dbus_bus_request_name[dbus]"); wpa_printf(MSG_ERROR, "Could not request DBus service name: " "%s %s.", error.name, error.message); break; } dbus_error_free(&error); if (ret != 0) goto fail; wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE "'."); /* * Dispatch initial DBus messages that may have come in since the bus * name was claimed above. Happens when clients are quick to notice the * wpa_supplicant service. * * FIXME: is there a better solution to this problem? */ eloop_register_timeout(0, 50, dispatch_initial_dbus_messages, iface->con, NULL); return iface;fail: wpa_supplicant_dbus_ctrl_iface_deinit(iface); return NULL;}/** * wpa_supplicant_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface * @iface: Pointer to dbus private data from * wpa_supplicant_dbus_ctrl_iface_init() * * Deinitialize the dbus control interface that was initialized with * wpa_supplicant_dbus_ctrl_iface_init(). */void wpa_supplicant_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_priv *iface){ if (iface == NULL) return; if (iface->con) { eloop_cancel_timeout(dispatch_initial_dbus_messages, iface->con, NULL); dbus_connection_set_watch_functions(iface->con, NULL, NULL, NULL, NULL, NULL); dbus_connection_set_timeout_functions(iface->con, NULL, NULL, NULL, NULL, NULL); dbus_connection_unref(iface->con); } memset(iface, 0, sizeof(struct ctrl_iface_dbus_priv)); free(iface);}/** * wpas_dbus_register_new_iface - Register a new interface with dbus * @global: Global %wpa_supplicant data * @wpa_s: %wpa_supplicant interface description structure to register * Returns: 0 on success, -1 on error * * Registers a new interface with dbus and assigns it a dbus object path. */int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s){ struct ctrl_iface_dbus_priv *ctrl_iface = wpa_s->global->dbus_ctrl_iface; DBusConnection * con; u32 next; DBusObjectPathVTable vtable = { NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL }; char *path; int ret = -1; /* Do nothing if the control interface is not turned on */ if (ctrl_iface == NULL) return 0; con = ctrl_iface->con; next = wpa_supplicant_dbus_next_objid(ctrl_iface); /* Create and set the interface's object path */ path = wpa_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); if (path == NULL) return -1; snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, WPAS_DBUS_PATH_INTERFACES "/%u", next); if (wpa_supplicant_set_dbus_path(wpa_s, path)) { wpa_printf(MSG_DEBUG, "Failed to set dbus path for interface %s", wpa_s->ifname); goto out; } /* Register the message handler for the interface functions */ if (!dbus_connection_register_fallback(con, path, &vtable, wpa_s)) { perror("wpas_dbus_register_iface [dbus]"); wpa_printf(MSG_ERROR, "Could not set up DBus message " "handler for interface %s.", wpa_s->ifname); goto out; } ret = 0;out: free(path); return ret;}/** * wpas_dbus_unregister_iface - Unregister an interface from dbus * @wpa_s: wpa_supplicant interface structure * Returns: 0 on success, -1 on failure * * Unregisters the interface with dbus */int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s){ struct ctrl_iface_dbus_priv *ctrl_iface; DBusConnection *con; const char *path; /* Do nothing if the control interface is not turned on */ if (wpa_s == NULL || wpa_s->global == NULL) return 0; ctrl_iface = wpa_s->global->dbus_ctrl_iface; if (ctrl_iface == NULL) return 0; con = ctrl_iface->con; path = wpa_supplicant_get_dbus_path(wpa_s); if (!dbus_connection_unregister_object_path(con, path)) return -1; free(wpa_s->dbus_path); wpa_s->dbus_path = NULL; return 0;}/** * wpa_supplicant_get_iface_by_dbus_path - Get a new network interface * @global: Pointer to global data from wpa_supplicant_init() * @path: Pointer to a dbus object path representing an interface * Returns: Pointer to the interface or %NULL if not found */struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path( struct wpa_global *global, const char *path){ struct wpa_supplicant *wpa_s; for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { if (strcmp(wpa_s->dbus_path, path) == 0) return wpa_s; } return NULL;}/** * wpa_supplicant_set_dbus_path - Assign a dbus path to an interface * @wpa_s: wpa_supplicant interface structure * @path: dbus path to set on the interface * Returns: 0 on succes, -1 on error */int wpa_supplicant_set_dbus_path(struct wpa_supplicant *wpa_s, const char *path){ u32 len = strlen (path); if (len >= WPAS_DBUS_OBJECT_PATH_MAX) return -1; if (wpa_s->dbus_path) return -1; wpa_s->dbus_path = strdup(path); return 0;}/** * wpa_supplicant_get_dbus_path - Get an interface's dbus path * @wpa_s: %wpa_supplicant interface structure * Returns: Interface's dbus object path, or %NULL on error */const char * wpa_supplicant_get_dbus_path(struct wpa_supplicant *wpa_s){ return wpa_s->dbus_path;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -