⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctrl_iface_dbus.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * WPA Supplicant / dbus-based control interface * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#include <dbus/dbus.h>#include "common.h"#include "eloop.h"#include "wpa.h"#include "wpa_supplicant.h"#include "config.h"#include "eapol_sm.h"#include "wpa_supplicant_i.h"#include "ctrl_iface_dbus.h"#include "ctrl_iface_dbus_handlers.h"#include "l2_packet.h"#include "preauth.h"#include "wpa_ctrl.h"#include "eap.h"#define DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR)#define DBUS_VER(major, minor) ((major) << 8 | (minor))#if DBUS_VERSION < DBUS_VER(1,1)#define dbus_watch_get_unix_fd dbus_watch_get_fd#endifstruct ctrl_iface_dbus_priv {	DBusConnection *con;	int should_dispatch;	struct wpa_global *global;	u32 next_objid;};static void process_watch(struct ctrl_iface_dbus_priv *iface,			  DBusWatch *watch, eloop_event_type type){	dbus_connection_ref(iface->con);	iface->should_dispatch = 0;	if (type == EVENT_TYPE_READ)		dbus_watch_handle(watch, DBUS_WATCH_READABLE);	else if (type == EVENT_TYPE_WRITE)		dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);	else if (type == EVENT_TYPE_EXCEPTION)		dbus_watch_handle(watch, DBUS_WATCH_ERROR);	if (iface->should_dispatch) {		while (dbus_connection_get_dispatch_status(iface->con) ==		       DBUS_DISPATCH_DATA_REMAINS)			dbus_connection_dispatch(iface->con);		iface->should_dispatch = 0;	}	dbus_connection_unref(iface->con);}static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx){	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);}static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx){	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);}static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx){	process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);}static void connection_setup_add_watch(struct ctrl_iface_dbus_priv *iface,				       DBusWatch *watch){	unsigned int flags;	int fd;	if (!dbus_watch_get_enabled(watch))		return;	flags = dbus_watch_get_flags(watch);	fd = dbus_watch_get_unix_fd(watch);	eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,			    iface, watch);	if (flags & DBUS_WATCH_READABLE) {		eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,				    iface, watch);	}	if (flags & DBUS_WATCH_WRITABLE) {		eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,				    iface, watch);	}	dbus_watch_set_data(watch, iface, NULL);}static void connection_setup_remove_watch(struct ctrl_iface_dbus_priv *iface,					  DBusWatch *watch){	unsigned int flags;	int fd;	flags = dbus_watch_get_flags(watch);	fd = dbus_watch_get_unix_fd(watch);	eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);	if (flags & DBUS_WATCH_READABLE)		eloop_unregister_sock(fd, EVENT_TYPE_READ);	if (flags & DBUS_WATCH_WRITABLE)		eloop_unregister_sock(fd, EVENT_TYPE_WRITE);	dbus_watch_set_data(watch, NULL, NULL);}static dbus_bool_t add_watch(DBusWatch *watch, void *data){	connection_setup_add_watch(data, watch);	return TRUE;}static void remove_watch(DBusWatch *watch, void *data){	connection_setup_remove_watch(data, watch);}static void watch_toggled(DBusWatch *watch, void *data){	if (dbus_watch_get_enabled(watch))		add_watch(watch, data);	else		remove_watch(watch, data);}static void process_timeout(void *eloop_ctx, void *sock_ctx){	DBusTimeout *timeout = sock_ctx;	dbus_timeout_handle(timeout);}static void connection_setup_add_timeout(struct ctrl_iface_dbus_priv *iface,					 DBusTimeout *timeout){	if (!dbus_timeout_get_enabled(timeout))		return;	eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,			       process_timeout, iface, timeout);	dbus_timeout_set_data(timeout, iface, NULL);}static void connection_setup_remove_timeout(struct ctrl_iface_dbus_priv *iface,					    DBusTimeout *timeout){	eloop_cancel_timeout(process_timeout, iface, timeout);	dbus_timeout_set_data(timeout, NULL, NULL);}static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data){	if (!dbus_timeout_get_enabled(timeout))		return TRUE;	connection_setup_add_timeout(data, timeout);	return TRUE;}static void remove_timeout(DBusTimeout *timeout, void *data){	connection_setup_remove_timeout(data, timeout);}static void timeout_toggled(DBusTimeout *timeout, void *data){	if (dbus_timeout_get_enabled(timeout))		add_timeout(timeout, data);	else		remove_timeout(timeout, data);}static void process_wakeup_main(int sig, void *eloop_ctx, void *signal_ctx){	struct ctrl_iface_dbus_priv *iface = signal_ctx;	if (sig != SIGPOLL || !iface->con)		return;	if (dbus_connection_get_dispatch_status(iface->con) !=	    DBUS_DISPATCH_DATA_REMAINS)		return;	/* Only dispatch once - we do not want to starve other events */	dbus_connection_ref(iface->con);	dbus_connection_dispatch(iface->con);	dbus_connection_unref(iface->con);}/** * wakeup_main - Attempt to wake our mainloop up * @data: dbus control interface private data * * Try to wake up the main eloop so it will process * dbus events that may have happened. */static void wakeup_main(void *data){	struct ctrl_iface_dbus_priv *iface = data;	/* Use SIGPOLL to break out of the eloop select() */	raise(SIGPOLL);	iface->should_dispatch = 1;}/** * connection_setup_wakeup_main - Tell dbus about our wakeup_main function * @iface: dbus control interface private data * Returns: 0 on success, -1 on failure * * Register our wakeup_main handler with dbus */static int connection_setup_wakeup_main(struct ctrl_iface_dbus_priv *iface){	if (eloop_register_signal(SIGPOLL, process_wakeup_main, iface))		return -1;	dbus_connection_set_wakeup_main_function(iface->con, wakeup_main,						 iface, NULL);	return 0;}/** * wpa_supplicant_dbus_next_objid - Return next available object id * @iface: dbus control interface private data * Returns: Object id */u32 wpa_supplicant_dbus_next_objid (struct ctrl_iface_dbus_priv *iface){	return iface->next_objid++;}/** * wpas_dbus_decompose_object_path - Decompose an interface object path into parts * @path: The dbus object path * @network: (out) the configured network this object path refers to, if any * @bssid: (out) the scanned bssid this object path refers to, if any * Returns: The object path of the network interface this path refers to * * For a given object path, decomposes the object path into object id, network, * and BSSID parts, if those parts exist. */char * wpas_dbus_decompose_object_path(const char *path, char **network,				       char **bssid){	const unsigned int dev_path_prefix_len =		strlen(WPAS_DBUS_PATH_INTERFACES "/");	char *obj_path_only;	char *next_sep;	/* Be a bit paranoid about path */	if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/",			     dev_path_prefix_len))		return NULL;	/* Ensure there's something at the end of the path */	if ((path + dev_path_prefix_len)[0] == '\0')		return NULL;	obj_path_only = strdup(path);	if (obj_path_only == NULL)		return NULL;	next_sep = strchr(obj_path_only + dev_path_prefix_len, '/');	if (next_sep != NULL) {		const char *net_part = strstr(next_sep,					      WPAS_DBUS_NETWORKS_PART "/");		const char *bssid_part = strstr(next_sep,						WPAS_DBUS_BSSIDS_PART "/");		if (network && net_part) {			/* Deal with a request for a configured network */			const char *net_name = net_part +				strlen(WPAS_DBUS_NETWORKS_PART "/");			*network = NULL;			if (strlen(net_name))				*network = strdup(net_name);		} else if (bssid && bssid_part) {			/* Deal with a request for a scanned BSSID */			const char *bssid_name = bssid_part +				strlen(WPAS_DBUS_BSSIDS_PART "/");			if (strlen(bssid_name))				*bssid = strdup(bssid_name);			else				*bssid = NULL;		}		/* Cut off interface object path before "/" */		*next_sep = '\0';	}	return obj_path_only;}/** * wpas_dbus_new_invalid_iface_error - Return a new invalid interface error message * @message: Pointer to incoming dbus message this error refers to * Returns: A dbus error message * * Convenience function to create and return an invalid interface error */DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message){	return dbus_message_new_error(message, WPAS_ERROR_INVALID_IFACE,				      "wpa_supplicant knows nothing about "				      "this interface.");}/** * wpas_dbus_new_invalid_network_error - Return a new invalid network error message * @message: Pointer to incoming dbus message this error refers to * Returns: a dbus error message * * Convenience function to create and return an invalid network error */DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message){	return dbus_message_new_error(message, WPAS_ERROR_INVALID_NETWORK,				      "The requested network does not exist.");}/** * wpas_dbus_new_invalid_bssid_error - Return a new invalid bssid error message * @message: Pointer to incoming dbus message this error refers to * Returns: a dbus error message * * Convenience function to create and return an invalid bssid error */static DBusMessage * wpas_dbus_new_invalid_bssid_error(DBusMessage *message){	return dbus_message_new_error(message, WPAS_ERROR_INVALID_BSSID,				      "The BSSID requested was invalid.");}/** * wpas_dispatch_network_method - dispatch messages for configured networks * @message: the incoming dbus message * @wpa_s: a network interface's data * @network_id: id of the configured network we're interested in * Returns: a reply dbus message, or a dbus error message * * This function dispatches all incoming dbus messages for configured networks. */static DBusMessage * wpas_dispatch_network_method(DBusMessage *message,						  struct wpa_supplicant *wpa_s,						  int network_id){	DBusMessage *reply = NULL;	const char *method = dbus_message_get_member(message);	struct wpa_ssid *ssid;	ssid = wpa_config_get_network(wpa_s->conf, network_id);	if (ssid == NULL)		return wpas_dbus_new_invalid_network_error(message);	if (!strcmp(method, "set"))		reply = wpas_dbus_iface_set_network(message, wpa_s, ssid);	else if (!strcmp(method, "enable"))		reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid);	else if (!strcmp(method, "disable"))		reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid);	return reply;}/** * wpas_dispatch_bssid_method - dispatch messages for scanned networks * @message: the incoming dbus message * @wpa_s: a network interface's data * @bssid: bssid of the scanned network we're interested in * Returns: a reply dbus message, or a dbus error message * * This function dispatches all incoming dbus messages for scanned networks. */static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message,						struct wpa_supplicant *wpa_s,						const char *bssid){	DBusMessage *reply = NULL;	const char *method = dbus_message_get_member(message);	struct wpa_scan_result * res = NULL;	int i;	/* Ensure we actually have scan data */	if (wpa_s->scan_results == NULL &&	    wpa_supplicant_get_scan_results(wpa_s) < 0) {		reply = wpas_dbus_new_invalid_bssid_error(message);		goto out;	}	/* Find the bssid's scan data */	for (i = 0; i < wpa_s->num_scan_results; i++) {		struct wpa_scan_result * search_res = &wpa_s->scan_results[i];		char mac_str[18];		memset(mac_str, 0, sizeof(mac_str));		snprintf(mac_str, sizeof(mac_str) - 1, WPAS_DBUS_BSSID_FORMAT,			 MAC2STR(search_res->bssid));		if (!strcmp(bssid, mac_str)) {			res = search_res;		}	}	if (!res) {		reply = wpas_dbus_new_invalid_bssid_error(message);		goto out;	}	/* Dispatch the method call against the scanned bssid */	if (!strcmp(method, "properties"))		reply = wpas_dbus_bssid_properties(message, wpa_s, res);out:	return reply;}/** * wpas_iface_message_handler - Dispatch messages for interfaces or networks * @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 for network interfaces, * or objects owned by them, such as scanned BSSIDs and configured networks. */static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection,						    DBusMessage *message,						    void *user_data){	struct wpa_supplicant *wpa_s = user_data;	const char *method = dbus_message_get_member(message);	const char *path = dbus_message_get_path(message);	const char *msg_interface = dbus_message_get_interface(message);	char *iface_obj_path = NULL;	char *network = NULL;	char *bssid = NULL;	DBusMessage *reply = NULL;	/* Caller must specify a message interface */	if (!msg_interface)		goto out;	iface_obj_path = wpas_dbus_decompose_object_path(path, &network,	                                                 &bssid);	if (iface_obj_path == NULL) {		reply = wpas_dbus_new_invalid_iface_error(message);		goto out;	}	/* Make sure the message's object path actually refers to the	 * wpa_supplicant structure it's supposed to (which is wpa_s)	 */	if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global,	                                          iface_obj_path) != wpa_s) {		reply = wpas_dbus_new_invalid_iface_error(message);		goto out;	}	if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) {		/* A method for one of this interface's configured networks */		int nid = strtoul(network, NULL, 10);		if (errno != EINVAL)			reply = wpas_dispatch_network_method(message, wpa_s,							     nid);		else			reply = wpas_dbus_new_invalid_network_error(message);	} else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) {		/* A method for one of this interface's scanned BSSIDs */		reply = wpas_dispatch_bssid_method(message, wpa_s, bssid);	} else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) {		/* A method for an interface only. */		if (!strcmp(method, "scan"))			reply = wpas_dbus_iface_scan(message, wpa_s);		else if (!strcmp(method, "scanResults"))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -