2006-12-19 Dan Williams <dcbw@redhat.com>

Big wpa_supplicant + dbus update; need latest wpa_supplicant from CVS
	plus a few other patches from wpa_supplicant bugzilla.

	* src/Makefile.am
	  src/NetworkManagerPolicy.c
	  src/NetworkManagerUtils.c
	  src/NetworkManagerUtils.h
	  src/nm-ap-security-leap.c
	  src/nm-ap-security-wep.c
	  src/nm-ap-security-wpa-eap.c
	  src/nm-ap-security-wpa-psk.c
	  src/nm-ap-security.c
	  src/nm-ap-security.h
	  src/nm-device-802-11-wireless.c
	  src/nm-device-802-11-wireless.h
	  src/supplicant-manager/nm-supplicant-config.c
	  src/supplicant-manager/nm-supplicant-config.h
	  src/supplicant-manager/nm-supplicant-interface.c
	  src/supplicant-manager/nm-supplicant-interface.h
	  src/supplicant-manager/nm-supplicant-marshal.list
	  src/supplicant-manager/nm-supplicant-settings-verify.c
	  src/supplicant-manager/nm-supplicant-settings-verify.h
		- Move all connection management and association handling to
			wpa_supplicant over dbus, rather than spawning a private copy


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2192 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2006-12-19 19:15:31 +00:00
parent 3834255f8c
commit a6f5833cb3
22 changed files with 1594 additions and 1539 deletions

View File

@@ -1,3 +1,30 @@
2006-12-19 Dan Williams <dcbw@redhat.com>
Big wpa_supplicant + dbus update; need latest wpa_supplicant from CVS
plus a few other patches from wpa_supplicant bugzilla.
* src/Makefile.am
src/NetworkManagerPolicy.c
src/NetworkManagerUtils.c
src/NetworkManagerUtils.h
src/nm-ap-security-leap.c
src/nm-ap-security-wep.c
src/nm-ap-security-wpa-eap.c
src/nm-ap-security-wpa-psk.c
src/nm-ap-security.c
src/nm-ap-security.h
src/nm-device-802-11-wireless.c
src/nm-device-802-11-wireless.h
src/supplicant-manager/nm-supplicant-config.c
src/supplicant-manager/nm-supplicant-config.h
src/supplicant-manager/nm-supplicant-interface.c
src/supplicant-manager/nm-supplicant-interface.h
src/supplicant-manager/nm-supplicant-marshal.list
src/supplicant-manager/nm-supplicant-settings-verify.c
src/supplicant-manager/nm-supplicant-settings-verify.h
- Move all connection management and association handling to
wpa_supplicant over dbus, rather than spawning a private copy
2006-12-19 Dan Williams <dcbw@redhat.com> 2006-12-19 Dan Williams <dcbw@redhat.com>
* src/NetworkManagerPolicy.c * src/NetworkManagerPolicy.c

View File

@@ -70,9 +70,7 @@ NetworkManager_SOURCES = \
nm-marshal-main.c \ nm-marshal-main.c \
kernel-types.h \ kernel-types.h \
wpa.c \ wpa.c \
wpa.h \ wpa.h
wpa_ctrl.c \
wpa_ctrl.h
nm-marshal.h: Makefile.am nm-marshal.list nm-marshal.h: Makefile.am nm-marshal.list
$(GLIB_GENMARSHAL) --prefix=nm_marshal $(srcdir)/nm-marshal.list --header > \ $(GLIB_GENMARSHAL) --prefix=nm_marshal $(srcdir)/nm-marshal.list --header > \

View File

@@ -255,11 +255,15 @@ static NMDevice * nm_policy_auto_get_best_device (NMData *data, NMAccessPoint **
highest_priority_dev = NM_DEVICE (best_wired_dev); highest_priority_dev = NM_DEVICE (best_wired_dev);
else if (best_wireless_dev) else if (best_wireless_dev)
{ {
gboolean can_activate;
can_activate = nm_device_802_11_wireless_can_activate (best_wireless_dev);
*ap = nm_device_802_11_wireless_get_best_ap (best_wireless_dev); *ap = nm_device_802_11_wireless_get_best_ap (best_wireless_dev);
/* If the device doesn't have a "best" ap, then we can't use it */ /* If the device doesn't have a "best" ap, then we can't use it */
if (!*ap) if (!*ap)
highest_priority_dev = NULL; highest_priority_dev = NULL;
else else if (can_activate == TRUE)
highest_priority_dev = NM_DEVICE (best_wireless_dev); highest_priority_dev = NM_DEVICE (best_wireless_dev);
} }

View File

@@ -39,7 +39,6 @@
#include "nm-device.h" #include "nm-device.h"
#include "nm-device-802-11-wireless.h" #include "nm-device-802-11-wireless.h"
#include "nm-device-802-3-ethernet.h" #include "nm-device-802-3-ethernet.h"
#include "wpa_ctrl.h"
#include <netlink/addr.h> #include <netlink/addr.h>
#include <netinet/in.h> #include <netinet/in.h>
@@ -716,129 +715,3 @@ int nm_utils_ip4_netmask_to_prefix (guint32 ip4_netmask)
return (32 - (i-1)); return (32 - (i-1));
} }
#define SUPPLICANT_DEBUG
#define RESPONSE_SIZE 2048
static char *
kill_newline (char *s, size_t *l)
{
g_return_val_if_fail (l != NULL, s);
while ((--(*l) > 0) && (s[*l] != '\n'))
;
if (s[*l] == '\n')
s[*l] = '\0';
return s;
}
char *
nm_utils_supplicant_request (struct wpa_ctrl *ctrl,
const char *format,
...)
{
va_list args;
size_t len;
char * response = NULL;
char * command;
g_return_val_if_fail (ctrl != NULL, NULL);
g_return_val_if_fail (format != NULL, NULL);
va_start (args, format);
if (!(command = g_strdup_vprintf (format, args)))
return NULL;
va_end (args);
response = g_malloc (RESPONSE_SIZE);
len = RESPONSE_SIZE;
#ifdef SUPPLICANT_DEBUG
nm_info ("SUP: sending command '%s'", command);
#endif
wpa_ctrl_request (ctrl, command, strlen (command), response, &len, NULL);
g_free (command);
response[len] = '\0';
#ifdef SUPPLICANT_DEBUG
{
response = kill_newline (response, &len);
nm_info ("SUP: response was '%s'", response);
}
#endif
return response;
}
gboolean
nm_utils_supplicant_request_with_check (struct wpa_ctrl *ctrl,
const char *expected,
const char *func,
const char *err_msg_cmd,
const char *format,
...)
{
va_list args;
gboolean success = FALSE;
size_t len;
char * response = NULL;
char * command;
char * temp;
g_return_val_if_fail (ctrl != NULL, FALSE);
g_return_val_if_fail (expected != NULL, FALSE);
g_return_val_if_fail (format != NULL, FALSE);
va_start (args, format);
if (!(command = g_strdup_vprintf (format, args)))
goto out;
response = g_malloc (RESPONSE_SIZE);
len = RESPONSE_SIZE;
#ifdef SUPPLICANT_DEBUG
/* Hack: don't print anything out for SCAN commands since they
* happen so often.
*/
if (strcmp (command, "SCAN") != 0)
nm_info ("SUP: sending command '%s'", err_msg_cmd ? err_msg_cmd : command);
#endif
wpa_ctrl_request (ctrl, command, strlen (command), response, &len, NULL);
response[len] = '\0';
#ifdef SUPPLICANT_DEBUG
/* Hack: don't print anything out for SCAN commands since they
* happen so often.
*/
if (strcmp (command, "SCAN") != 0) {
response = kill_newline (response, &len);
nm_info ("SUP: response was '%s'", response);
}
#endif
if (response)
{
if (strncmp (response, expected, strlen (expected)) == 0)
success = TRUE;
else
{
response = kill_newline (response, &len);
temp = g_strdup_printf ("%s: supplicant error for '%s'. Response: '%s'",
func, err_msg_cmd ? err_msg_cmd : command, response);
nm_warning_str (temp);
g_free (temp);
}
g_free (response);
}
else
{
temp = g_strdup_printf ("%s: supplicant error for '%s'. No response.",
func, err_msg_cmd ? err_msg_cmd : command);
nm_warning_str (temp);
g_free (temp);
}
g_free (command);
out:
va_end (args);
return success;
}

View File

@@ -107,15 +107,4 @@ struct nl_addr * nm_utils_ip4_addr_to_nl_addr (guint32 ip4_addr);
int nm_utils_ip4_netmask_to_prefix (guint32 ip4_netmask); int nm_utils_ip4_netmask_to_prefix (guint32 ip4_netmask);
char * nm_utils_supplicant_request (struct wpa_ctrl *ctrl,
const char *format,
...);
gboolean nm_utils_supplicant_request_with_check (struct wpa_ctrl *ctrl,
const char *expected,
const char *func,
const char *alt_cmd_for_err_msg,
const char *format,
...);
#endif #endif

View File

@@ -29,7 +29,7 @@
#include "nm-ap-security-private.h" #include "nm-ap-security-private.h"
#include "dbus-helpers.h" #include "dbus-helpers.h"
#include "nm-device-802-11-wireless.h" #include "nm-device-802-11-wireless.h"
#include "NetworkManagerUtils.h" #include "nm-supplicant-config.h"
#define NM_AP_SECURITY_LEAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_LEAP, NMAPSecurityLEAPPrivate)) #define NM_AP_SECURITY_LEAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_LEAP, NMAPSecurityLEAPPrivate))
@@ -98,42 +98,32 @@ real_serialize (NMAPSecurity *instance, DBusMessageIter *iter)
static gboolean static gboolean
real_write_supplicant_config (NMAPSecurity *instance, real_write_supplicant_config (NMAPSecurity *instance,
struct wpa_ctrl *ctrl, NMSupplicantConfig * config,
int nwid,
gboolean user_created) gboolean user_created)
{ {
NMAPSecurityLEAP * self = NM_AP_SECURITY_LEAP (instance); NMAPSecurityLEAP * self = NM_AP_SECURITY_LEAP (instance);
gboolean success = FALSE; gboolean success = FALSE;
char * msg;
const char * password = nm_ap_security_get_key (instance); const char * password = nm_ap_security_get_key (instance);
g_return_val_if_fail (nm_ap_security_get_we_cipher (instance) == NM_AUTH_TYPE_LEAP, FALSE); g_return_val_if_fail (nm_ap_security_get_we_cipher (instance) == NM_AUTH_TYPE_LEAP, FALSE);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i proto WPA", nwid)) if (!nm_supplicant_config_add_option (config, "proto", "WPA", -1))
goto out; goto out;
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i key_mgmt %s", if (!nm_supplicant_config_add_option (config, "key_mgmt", self->priv->key_mgmt, -1))
nwid, self->priv->key_mgmt))
goto out; goto out;
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i eap LEAP", nwid)) if (!nm_supplicant_config_add_option (config, "eap", "LEAP", -1))
goto out; goto out;
if (self->priv->username && strlen (self->priv->username) > 0) if (self->priv->username && strlen (self->priv->username) > 0) {
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i identity \"%s\"", if (!nm_supplicant_config_add_option (config, "identity", self->priv->username, -1))
nwid, self->priv->username))
goto out;
if (password && strlen (password) > 0)
{
msg = g_strdup_printf ("SET_NETWORK %i password <password>", nwid);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, msg, "SET_NETWORK %i password \"%s\"",
nwid, password))
{
g_free (msg);
goto out; goto out;
} }
g_free (msg);
if (password && strlen (password) > 0) {
if (!nm_supplicant_config_add_option (config, "password", password, -1))
goto out;
} }
success = TRUE; success = TRUE;

View File

@@ -30,7 +30,7 @@
#include "dbus-helpers.h" #include "dbus-helpers.h"
#include "nm-device-802-11-wireless.h" #include "nm-device-802-11-wireless.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "NetworkManagerUtils.h" #include "nm-supplicant-config.h"
#define NM_AP_SECURITY_WEP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_WEP, NMAPSecurityWEPPrivate)) #define NM_AP_SECURITY_WEP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_WEP, NMAPSecurityWEPPrivate))
@@ -113,40 +113,39 @@ real_serialize (NMAPSecurity *instance, DBusMessageIter *iter)
static gboolean static gboolean
real_write_supplicant_config (NMAPSecurity *instance, real_write_supplicant_config (NMAPSecurity *instance,
struct wpa_ctrl *ctrl, NMSupplicantConfig * config,
int nwid,
gboolean adhoc) gboolean adhoc)
{ {
gboolean success = FALSE; gboolean success = FALSE;
char * msg = NULL;
const char * key = nm_ap_security_get_key (instance); const char * key = nm_ap_security_get_key (instance);
char * bin_key = NULL;
/* WEP network setup */ /* WEP network setup */
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, if (!nm_supplicant_config_add_option (config, "key_mgmt", "NONE", -1))
"SET_NETWORK %i key_mgmt NONE", nwid))
goto out; goto out;
/* /*
* If the user selected "Shared" (aka restricted) key, set it explicitly. Otherwise, * If the user selected "Shared" (aka restricted) key, set it explicitly. Otherwise,
* let wpa_supplicant default to the right thing, which is an open key. * let wpa_supplicant default to the right thing, which is an open key.
*/ */
if (get_auth_algorithm (NM_AP_SECURITY_WEP (instance)) == IW_AUTH_ALG_SHARED_KEY) if (get_auth_algorithm (NM_AP_SECURITY_WEP (instance)) == IW_AUTH_ALG_SHARED_KEY) {
{ if (!nm_supplicant_config_add_option (config, "auth_alg", "SHARED", -1))
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, msg,
"SET_NETWORK %i auth_alg SHARED", nwid));
}
msg = g_strdup_printf ("SET_NETWORK %i wep_key0 <key>", nwid);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, msg,
"SET_NETWORK %i wep_key0 %s", nwid, key))
{
g_free (msg);
goto out; goto out;
} }
g_free (msg);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, bin_key = cipher_hexstr2bin(key, strlen (key));
"SET_NETWORK %i wep_tx_keyidx 0", nwid)) if (bin_key == NULL) {
nm_warning ("Not enough memory to convert key.");
goto out;
}
if (!nm_supplicant_config_add_option (config, "wep_key0", bin_key, -1)) {
g_free (bin_key);
goto out;
}
g_free (bin_key);
if (!nm_supplicant_config_add_option (config, "wep_tx_keyidx", "0", -1))
goto out; goto out;
success = TRUE; success = TRUE;

View File

@@ -30,7 +30,7 @@
#include "nm-ap-security-private.h" #include "nm-ap-security-private.h"
#include "dbus-helpers.h" #include "dbus-helpers.h"
#include "nm-device-802-11-wireless.h" #include "nm-device-802-11-wireless.h"
#include "NetworkManagerUtils.h" #include "nm-supplicant-config.h"
#define NM_AP_SECURITY_WPA_EAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_WPA_EAP, NMAPSecurityWPA_EAPPrivate)) #define NM_AP_SECURITY_WPA_EAP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_WPA_EAP, NMAPSecurityWPA_EAPPrivate))
@@ -167,13 +167,11 @@ get_eap_method (int eap_method)
static gboolean static gboolean
real_write_supplicant_config (NMAPSecurity *instance, real_write_supplicant_config (NMAPSecurity *instance,
struct wpa_ctrl *ctrl, NMSupplicantConfig * config,
int nwid,
gboolean adhoc) gboolean adhoc)
{ {
NMAPSecurityWPA_EAP * self = NM_AP_SECURITY_WPA_EAP (instance); NMAPSecurityWPA_EAP * self = NM_AP_SECURITY_WPA_EAP (instance);
gboolean success = FALSE; gboolean success = FALSE;
char * msg;
const char * identity = self->priv->identity; const char * identity = self->priv->identity;
const char * anon_identity = self->priv->anon_identity; const char * anon_identity = self->priv->anon_identity;
const char * passwd = self->priv->passwd; const char * passwd = self->priv->passwd;
@@ -204,80 +202,66 @@ real_write_supplicant_config (NMAPSecurity *instance,
/* WPA-EAP network setup */ /* WPA-EAP network setup */
if (self->priv->wpa_version == IW_AUTH_WPA_VERSION_WPA) if (self->priv->wpa_version == IW_AUTH_WPA_VERSION_WPA) {
{ if (!nm_supplicant_config_add_option (config, "proto", "WPA", -1))
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i proto WPA", nwid))
goto out; goto out;
} } else {
else if (!nm_supplicant_config_add_option (config, "proto", "WPA2", -1))
{
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i proto WPA2", nwid))
goto out; goto out;
} }
if (key_type != IW_AUTH_CIPHER_WEP104) if (key_type != IW_AUTH_CIPHER_WEP104) {
{ if (!nm_supplicant_config_add_option (config, "key_mgmt", "WPA-EAP", -1))
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i key_mgmt WPA-EAP", nwid))
goto out; goto out;
} } else {
else
{
/* So-called Dynamic WEP */ /* So-called Dynamic WEP */
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i key_mgmt IEEE8021X", nwid)) if (!nm_supplicant_config_add_option (config, "key_mgmt", "IEEE8021X", -1))
goto out; goto out;
} }
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i eap %s", nwid, get_eap_method (eap_method))) if (!nm_supplicant_config_add_option (config, "eap", get_eap_method (eap_method), -1))
goto out; goto out;
if (identity && strlen (identity) > 0) if (identity && strlen (identity) > 0) {
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i identity \"%s\"", nwid, identity)) if (!nm_supplicant_config_add_option (config, "identity", identity, -1))
goto out;
if (passwd && strlen (passwd) > 0)
{
msg = g_strdup_printf ("SET_NETWORK %i password <password>", nwid);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, msg, "SET_NETWORK %i password \"%s\"", nwid, passwd))
{
g_free (msg);
goto out; goto out;
} }
g_free (msg);
}
if (anon_identity && strlen (anon_identity) > 0) if (passwd && strlen (passwd) > 0) {
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i anonymous_identity \"%s\"", nwid, anon_identity)) if (!nm_supplicant_config_add_option (config, "password", passwd, -1))
goto out;
if (private_key_file && strlen (private_key_file) > 0)
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i private_key \"%s\"", nwid, private_key_file))
goto out;
if (private_key_passwd && strlen (private_key_passwd) > 0)
{
msg = g_strdup_printf ("SET_NETWORK %i private_key_passwd <key>", nwid);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, msg, "SET_NETWORK %i private_key_passwd \"%s\"", nwid, private_key_passwd))
{
g_free (msg);
goto out; goto out;
} }
g_free (msg);
if (anon_identity && strlen (anon_identity) > 0) {
if (!nm_supplicant_config_add_option (config, "anonymous_identity", anon_identity, -1))
goto out;
} }
if (client_cert_file && strlen (client_cert_file) > 0) if (private_key_file && strlen (private_key_file) > 0) {
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i client_cert \"%s\"", nwid, client_cert_file)) if (!nm_supplicant_config_add_option (config, "private_key", private_key_file, -1))
goto out; goto out;
}
if (ca_cert_file && strlen (ca_cert_file) > 0) if (private_key_passwd && strlen (private_key_passwd) > 0) {
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, "SET_NETWORK %i ca_cert \"%s\"", nwid, ca_cert_file)) if (!nm_supplicant_config_add_option (config, "private_key_passwd", private_key_passwd, -1))
goto out; goto out;
}
if (client_cert_file && strlen (client_cert_file) > 0) {
if (!nm_supplicant_config_add_option (config, "client_cert", client_cert_file, -1))
goto out;
}
if (ca_cert_file && strlen (ca_cert_file) > 0) {
if (!nm_supplicant_config_add_option (config, "ca_cert", ca_cert_file, -1))
goto out;
}
/* /*
* Set the pairwise and group cipher, if the user provided one. If user selected "Automatic", we * Set the pairwise and group cipher, if the user provided one. If user selected "Automatic", we
* let wpa_supplicant sort it out. Likewise, if the user selected "Dynamic WEP", we do nothing. * let wpa_supplicant sort it out. Likewise, if the user selected "Dynamic WEP", we do nothing.
*/ */
if (key_type != NM_AUTH_TYPE_WPA_PSK_AUTO && key_type != IW_AUTH_CIPHER_WEP104) if (key_type != NM_AUTH_TYPE_WPA_PSK_AUTO && key_type != IW_AUTH_CIPHER_WEP104) {
{
const char *cipher; const char *cipher;
/* /*
@@ -289,12 +273,10 @@ real_write_supplicant_config (NMAPSecurity *instance,
else /* IW_AUTH_CIPHER_CCMP */ else /* IW_AUTH_CIPHER_CCMP */
cipher = "CCMP"; cipher = "CCMP";
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, if (!nm_supplicant_config_add_option (config, "pairwise", cipher, -1))
"SET_NETWORK %i pairwise %s", nwid, cipher))
goto out; goto out;
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, if (!nm_supplicant_config_add_option (config, "group", cipher, -1))
"SET_NETWORK %i group %s", nwid, cipher))
goto out; goto out;
} }

View File

@@ -29,7 +29,8 @@
#include "nm-ap-security-private.h" #include "nm-ap-security-private.h"
#include "dbus-helpers.h" #include "dbus-helpers.h"
#include "nm-device-802-11-wireless.h" #include "nm-device-802-11-wireless.h"
#include "NetworkManagerUtils.h" #include "nm-supplicant-config.h"
#include "nm-utils.h"
#define NM_AP_SECURITY_WPA_PSK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_WPA_PSK, NMAPSecurityWPA_PSKPrivate)) #define NM_AP_SECURITY_WPA_PSK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_WPA_PSK, NMAPSecurityWPA_PSKPrivate))
@@ -132,31 +133,25 @@ real_serialize (NMAPSecurity *instance, DBusMessageIter *iter)
static gboolean static gboolean
real_write_supplicant_config (NMAPSecurity *instance, real_write_supplicant_config (NMAPSecurity *instance,
struct wpa_ctrl *ctrl, NMSupplicantConfig * config,
int nwid,
gboolean adhoc) gboolean adhoc)
{ {
NMAPSecurityWPA_PSK * self = NM_AP_SECURITY_WPA_PSK (instance); NMAPSecurityWPA_PSK * self = NM_AP_SECURITY_WPA_PSK (instance);
gboolean success = FALSE; gboolean success = FALSE;
char * msg = NULL;
const char * key = nm_ap_security_get_key (instance); const char * key = nm_ap_security_get_key (instance);
int cipher = nm_ap_security_get_we_cipher (instance); int cipher = nm_ap_security_get_we_cipher (instance);
char * key_mgmt = "WPA-PSK"; char * key_mgmt = "WPA-PSK";
char * pairwise_cipher = NULL; char * pairwise_cipher = NULL;
char * group_cipher = NULL; char * group_cipher = NULL;
char * bin_key = NULL;
/* WPA-PSK network setup */ /* WPA-PSK network setup */
if (self->priv->wpa_version == IW_AUTH_WPA_VERSION_WPA) if (self->priv->wpa_version == IW_AUTH_WPA_VERSION_WPA) {
{ if (!nm_supplicant_config_add_option (config, "proto", "WPA", -1))
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i proto WPA", nwid))
goto out; goto out;
} } else if (self->priv->wpa_version == IW_AUTH_WPA_VERSION_WPA2) {
else if (self->priv->wpa_version == IW_AUTH_WPA_VERSION_WPA2) if (!nm_supplicant_config_add_option (config, "proto", "WPA2", -1))
{
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i proto WPA2", nwid))
goto out; goto out;
} }
@@ -164,18 +159,20 @@ real_write_supplicant_config (NMAPSecurity *instance,
if (adhoc) if (adhoc)
key_mgmt = "WPA-NONE"; key_mgmt = "WPA-NONE";
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, if (!nm_supplicant_config_add_option (config, "key_mgmt", key_mgmt, -1))
"SET_NETWORK %i key_mgmt %s", nwid, key_mgmt))
goto out; goto out;
msg = g_strdup_printf ("SET_NETWORK %i psk <key>", nwid); bin_key = cipher_hexstr2bin(key, strlen (key));
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, msg, if (bin_key == NULL) {
"SET_NETWORK %i psk %s", nwid, key)) nm_warning ("Not enough memory to convert key.");
{
g_free (msg);
goto out; goto out;
} }
g_free (msg);
if (!nm_supplicant_config_add_option (config, "psk", bin_key, -1)) {
g_free (bin_key);
goto out;
}
g_free (bin_key);
/* /*
* FIXME: Technically, the pairwise cipher does not need to be the same as * FIXME: Technically, the pairwise cipher does not need to be the same as
@@ -193,14 +190,11 @@ real_write_supplicant_config (NMAPSecurity *instance,
pairwise_cipher = "NONE"; pairwise_cipher = "NONE";
/* If user selected "Automatic", we let wpa_supplicant sort it out */ /* If user selected "Automatic", we let wpa_supplicant sort it out */
if (cipher != NM_AUTH_TYPE_WPA_PSK_AUTO) if (cipher != NM_AUTH_TYPE_WPA_PSK_AUTO) {
{ if (!nm_supplicant_config_add_option (config, "pairwise", pairwise_cipher, -1))
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i pairwise %s", nwid, pairwise_cipher))
goto out; goto out;
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, if (!nm_supplicant_config_add_option (config, "group", group_cipher, -1))
"SET_NETWORK %i group %s", nwid, group_cipher))
goto out; goto out;
} }

View File

@@ -31,9 +31,8 @@
#include "nm-ap-security-wpa-eap.h" #include "nm-ap-security-wpa-eap.h"
#include "nm-ap-security-leap.h" #include "nm-ap-security-leap.h"
#include "nm-device-802-11-wireless.h" #include "nm-device-802-11-wireless.h"
#include "wpa_ctrl.h" #include "nm-supplicant-config.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "NetworkManagerUtils.h"
#define NM_AP_SECURITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY, NMAPSecurityPrivate)) #define NM_AP_SECURITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY, NMAPSecurityPrivate))
@@ -169,19 +168,18 @@ nm_ap_security_get_authentication_required (NMAPSecurity *self)
gboolean gboolean
nm_ap_security_write_supplicant_config (NMAPSecurity *self, nm_ap_security_write_supplicant_config (NMAPSecurity *self,
struct wpa_ctrl *ctrl, NMSupplicantConfig * config,
int nwid,
gboolean adhoc) gboolean adhoc)
{ {
NMAPSecurityClass * class = NM_AP_SECURITY_GET_CLASS (self);
g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (ctrl != NULL, FALSE); g_return_val_if_fail (config != NULL, FALSE);
g_return_val_if_fail (nwid >= 0, FALSE);
if (self->priv->dispose_has_run) if (self->priv->dispose_has_run)
return FALSE; return FALSE;
return NM_AP_SECURITY_GET_CLASS (self)->write_supplicant_config_func (self, return class->write_supplicant_config_func (self, config, adhoc);
ctrl, nwid, adhoc);
} }
void void
@@ -238,13 +236,11 @@ real_serialize (NMAPSecurity *self, DBusMessageIter *iter)
static gboolean static gboolean
real_write_supplicant_config (NMAPSecurity *self, real_write_supplicant_config (NMAPSecurity *self,
struct wpa_ctrl *ctrl, NMSupplicantConfig * config,
int nwid,
gboolean adhoc) gboolean adhoc)
{ {
/* Unencrypted network setup */ /* Unencrypted network */
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL, if (!nm_supplicant_config_add_option (config, "key_mgmt", "NONE", -1))
"SET_NETWORK %i key_mgmt NONE", nwid))
return FALSE; return FALSE;
return TRUE; return TRUE;

View File

@@ -25,6 +25,8 @@
#include <glib-object.h> #include <glib-object.h>
#include <dbus/dbus.h> #include <dbus/dbus.h>
#include "supplicant-manager/nm-supplicant-types.h"
/* Grr */ /* Grr */
#ifndef NM_DEVICE_802_11_WIRELESS_DEFINED #ifndef NM_DEVICE_802_11_WIRELESS_DEFINED
#define NM_DEVICE_802_11_WIRELESS_DEFINED #define NM_DEVICE_802_11_WIRELESS_DEFINED
@@ -53,7 +55,6 @@ struct _NMAPSecurity
}; };
struct NMAccessPoint; struct NMAccessPoint;
struct wpa_ctrl;
struct _NMAPSecurityClass struct _NMAPSecurityClass
{ {
@@ -62,11 +63,11 @@ struct _NMAPSecurityClass
/* class members */ /* class members */
NMAPSecurity * (*copy_constructor_func) (NMAPSecurity *self); NMAPSecurity * (*copy_constructor_func) (NMAPSecurity *self);
int (*serialize_func) (NMAPSecurity *self, DBusMessageIter *iter); int (*serialize_func) (NMAPSecurity *self,
DBusMessageIter *iter);
gboolean (*write_supplicant_config_func) (NMAPSecurity *self, gboolean (*write_supplicant_config_func) (NMAPSecurity *self,
struct wpa_ctrl *ctrl, NMSupplicantConfig * config,
int nwid,
gboolean adhoc); gboolean adhoc);
guint32 (*get_default_capabilities_func) (NMAPSecurity *self); guint32 (*get_default_capabilities_func) (NMAPSecurity *self);
@@ -92,8 +93,7 @@ int nm_ap_security_serialize (NMAPSecurity *self,
DBusMessageIter *iter); DBusMessageIter *iter);
gboolean nm_ap_security_write_supplicant_config (NMAPSecurity *self, gboolean nm_ap_security_write_supplicant_config (NMAPSecurity *self,
struct wpa_ctrl *ctrl, NMSupplicantConfig * config,
int nwid,
gboolean adhoc); gboolean adhoc);
const char * nm_ap_security_get_description (NMAPSecurity *self); const char * nm_ap_security_get_description (NMAPSecurity *self);

File diff suppressed because it is too large Load Diff

View File

@@ -120,6 +120,8 @@ int nm_device_802_11_wireless_get_mode (NMDevice80211Wireless *self);
gint8 nm_device_802_11_wireless_get_signal_strength (NMDevice80211Wireless *self); gint8 nm_device_802_11_wireless_get_signal_strength (NMDevice80211Wireless *self);
gboolean nm_device_802_11_wireless_can_activate (NMDevice80211Wireless * self);
G_END_DECLS G_END_DECLS

View File

@@ -19,11 +19,14 @@
* (C) Copyright 2006 Red Hat, Inc. * (C) Copyright 2006 Red Hat, Inc.
*/ */
#include <string.h>
#include <glib.h> #include <glib.h>
#include "nm-supplicant-config.h" #include "nm-supplicant-config.h"
#include "nm-supplicant-settings-verify.h" #include "nm-supplicant-settings-verify.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "dbus-dict-helpers.h"
#include "cipher.h"
#define NM_SUPPLICANT_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ #define NM_SUPPLICANT_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
NM_TYPE_SUPPLICANT_CONFIG, \ NM_TYPE_SUPPLICANT_CONFIG, \
@@ -34,10 +37,18 @@ static void nm_supplicant_config_set_device (NMSupplicantConfig *con,
NMDevice *dev); NMDevice *dev);
struct option {
char * key;
char * value;
guint32 len;
enum OptType type;
};
struct _NMSupplicantConfigPrivate struct _NMSupplicantConfigPrivate
{ {
NMDevice * dev; NMDevice * dev;
GHashTable * config; GSList * config;
guint32 ap_scan;
gboolean dispose_has_run; gboolean dispose_has_run;
}; };
@@ -57,8 +68,8 @@ static void
nm_supplicant_config_init (NMSupplicantConfig * self) nm_supplicant_config_init (NMSupplicantConfig * self)
{ {
self->priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self); self->priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
self->priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, self->priv->config = NULL;
g_free); self->priv->ap_scan = 1;
self->priv->dispose_has_run = FALSE; self->priv->dispose_has_run = FALSE;
} }
@@ -76,34 +87,100 @@ nm_supplicant_config_set_device (NMSupplicantConfig *self,
gboolean gboolean
nm_supplicant_config_add_option (NMSupplicantConfig *self, nm_supplicant_config_add_option (NMSupplicantConfig *self,
const char * key, const char * key,
const char * value) const char * value,
gint32 len)
{ {
GSList * elt;
struct option * opt;
OptType type;
g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (key != NULL, FALSE); g_return_val_if_fail (key != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE);
if (!nm_supplicant_settings_verify_setting (key, value)) { if (len < 0)
nm_debug ("Key '%s' and/or value '%s' invalid.", key, value); len = strlen (value);
type = nm_supplicant_settings_verify_setting (key, value, len);
if (type == TYPE_INVALID) {
char buf[255];
memset (&buf[0], 0, sizeof (buf));
memcpy (&buf[0], value, len > 254 ? 254 : len);
nm_debug ("Key '%s' and/or value '%s' invalid.", key, buf);
return FALSE; return FALSE;
} }
if (g_hash_table_lookup (self->priv->config, key)) { for (elt = self->priv->config; elt; elt = g_slist_next (elt)) {
struct option * tmp_opt = (struct option *) elt->data;
if (strcmp (tmp_opt->key, key) == 0) {
nm_debug ("Key '%s' already in table.", key); nm_debug ("Key '%s' already in table.", key);
return FALSE; return FALSE;
} }
}
opt = g_slice_new0 (struct option);
if (opt == NULL) {
nm_debug ("Couldn't allocate memory for new config option.");
return FALSE;
}
opt->key = g_strdup (key);
if (opt->key == NULL) {
nm_debug ("Couldn't allocate memory for new config option key.");
g_slice_free (struct option, opt);
return FALSE;
}
opt->value = g_malloc0 (sizeof (char) * len);
if (opt->value == NULL) {
nm_debug ("Couldn't allocate memory for new config option value.");
g_free (opt->key);
g_slice_free (struct option, opt);
return FALSE;
}
memcpy (opt->value, value, len);
opt->len = len;
opt->type = type;
self->priv->config = g_slist_append (self->priv->config, opt);
g_hash_table_insert (self->priv->config, g_strdup (key), g_strdup (value));
return TRUE; return TRUE;
} }
static void
free_option (struct option * opt)
{
g_return_if_fail (opt != NULL);
g_free (opt->key);
g_free (opt->value);
}
gboolean gboolean
nm_supplicant_config_remove_option (NMSupplicantConfig *self, nm_supplicant_config_remove_option (NMSupplicantConfig *self,
const char * key) const char * key)
{ {
GSList * elt;
GSList * found = NULL;
g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (key != NULL, FALSE); g_return_val_if_fail (key != NULL, FALSE);
return g_hash_table_remove (self->priv->config, key); for (elt = self->priv->config; elt; elt = g_slist_next (elt)) {
struct option * opt = (struct option *) elt->data;
if (strcmp (opt->key, key) == 0) {
found = elt;
break;
}
}
if (!found)
return FALSE;
self->priv->config = g_slist_remove_link (self->priv->config, found);
free_option (found->data);
g_slice_free (struct option, found->data);
g_slist_free1 (found);
return TRUE;
} }
static void static void
@@ -143,9 +220,15 @@ nm_supplicant_config_finalize (GObject *object)
NMSupplicantConfig * self = NM_SUPPLICANT_CONFIG (object); NMSupplicantConfig * self = NM_SUPPLICANT_CONFIG (object);
NMSupplicantConfigClass * klass; NMSupplicantConfigClass * klass;
GObjectClass * parent_class; GObjectClass * parent_class;
GSList * elt;
/* Complete object destruction */ /* Complete object destruction */
g_hash_table_destroy (self->priv->config); for (elt = self->priv->config; elt; elt = g_slist_next (elt)) {
free_option (elt->data);
g_slice_free (struct option, elt->data);
}
g_slist_free (self->priv->config);
self->priv->config = NULL;
/* Chain up to the parent class */ /* Chain up to the parent class */
klass = NM_SUPPLICANT_CONFIG_CLASS (g_type_class_peek (NM_TYPE_SUPPLICANT_CONFIG)); klass = NM_SUPPLICANT_CONFIG_CLASS (g_type_class_peek (NM_TYPE_SUPPLICANT_CONFIG));
@@ -189,3 +272,87 @@ nm_supplicant_config_get_type (void)
} }
return type; return type;
} }
guint32
nm_supplicant_config_get_ap_scan (NMSupplicantConfig * self)
{
g_return_val_if_fail (self != NULL, 1);
return self->priv->ap_scan;
}
void
nm_supplicant_config_set_ap_scan (NMSupplicantConfig * self,
guint32 ap_scan)
{
g_return_if_fail (self != NULL);
g_return_if_fail (ap_scan >= 0 && ap_scan <=2);
self->priv->ap_scan = ap_scan;
}
gboolean
nm_supplicant_config_add_to_dbus_message (NMSupplicantConfig * self,
DBusMessage * message)
{
GSList * elt;
DBusMessageIter iter, iter_dict;
gboolean success = FALSE;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (message != NULL, FALSE);
dbus_message_iter_init_append (message, &iter);
if (!nmu_dbus_dict_open_write (&iter, &iter_dict)) {
nm_warning ("dict open write failed!");
goto out;
}
for (elt = self->priv->config; elt; elt = g_slist_next (elt)) {
struct option * opt = (struct option *) elt->data;
switch (opt->type) {
case TYPE_INT:
if (!nmu_dbus_dict_append_string (&iter_dict, opt->key, opt->value)) {
nm_warning ("couldn't append INT option '%s' to dict", opt->key);
goto out;
}
break;
case TYPE_KEYWORD:
if (!nmu_dbus_dict_append_string (&iter_dict, opt->key, opt->value)) {
nm_warning ("couldn't append KEYWORD option '%s' to dict", opt->key);
goto out;
}
break;
case TYPE_BYTES:
{
if (!nmu_dbus_dict_append_byte_array (&iter_dict,
opt->key,
opt->value,
opt->len)) {
nm_warning ("couldn't append BYTES option '%s' to dict", opt->key);
goto out;
}
}
break;
default:
nm_warning ("unknown option '%s', type %d", opt->key, opt->type);
goto out;
break;
}
}
if (!nmu_dbus_dict_close_write (&iter, &iter_dict)) {
nm_warning ("dict close write failed!");
goto out;
}
success = TRUE;
out:
return success;
}

View File

@@ -60,11 +60,20 @@ NMSupplicantConfig * nm_supplicant_config_new (NMDevice *dev);
gboolean nm_supplicant_config_add_option (NMSupplicantConfig *scfg, gboolean nm_supplicant_config_add_option (NMSupplicantConfig *scfg,
const char * key, const char * key,
const char * value); const char * value,
gint32 len);
gboolean nm_supplicant_config_remove_option (NMSupplicantConfig *self, gboolean nm_supplicant_config_remove_option (NMSupplicantConfig *self,
const char * key); const char * key);
guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig * self);
void nm_supplicant_config_set_ap_scan (NMSupplicantConfig * self,
guint32 ap_scan);
gboolean nm_supplicant_config_add_to_dbus_message (NMSupplicantConfig * self,
DBusMessage * message);
G_END_DECLS G_END_DECLS
#endif /* NM_SUPPLICANT_CONFIG_H */ #endif /* NM_SUPPLICANT_CONFIG_H */

View File

@@ -28,6 +28,7 @@
#include "nm-device-802-3-ethernet.h" #include "nm-device-802-3-ethernet.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "nm-supplicant-marshal.h" #include "nm-supplicant-marshal.h"
#include "nm-supplicant-config.h"
#include "nm-dbus-manager.h" #include "nm-dbus-manager.h"
#include "dbus-dict-helpers.h" #include "dbus-dict-helpers.h"
#include "NetworkManagerMain.h" #include "NetworkManagerMain.h"
@@ -71,6 +72,7 @@ enum {
SCANNED_AP, /* interface saw a new access point from a scan */ SCANNED_AP, /* interface saw a new access point from a scan */
SCAN_RESULT, /* result of a wireless scan request */ SCAN_RESULT, /* result of a wireless scan request */
CONNECTION_STATE, /* link state of the device's connection */ CONNECTION_STATE, /* link state of the device's connection */
CONNECTION_ERROR, /* an error occurred during a connection request */
LAST_SIGNAL LAST_SIGNAL
}; };
static guint nm_supplicant_interface_signals[LAST_SIGNAL] = { 0 }; static guint nm_supplicant_interface_signals[LAST_SIGNAL] = { 0 };
@@ -95,7 +97,8 @@ struct _NMSupplicantInterfacePrivate
NMDevice * dev; NMDevice * dev;
guint32 state; guint32 state;
GSList * pcalls; GSList * assoc_pcalls;
GSList * other_pcalls;
guint32 con_state; guint32 con_state;
@@ -110,61 +113,61 @@ struct _NMSupplicantInterfacePrivate
gboolean dispose_has_run; gboolean dispose_has_run;
}; };
static void static GSList *
add_pcall (NMSupplicantInterface * self, pcall_list_add_pcall (GSList * pcall_list,
DBusPendingCall * pcall) DBusPendingCall * pcall)
{ {
GSList * elt; GSList * elt;
g_return_if_fail (self != NULL); g_return_val_if_fail (pcall != NULL, pcall_list);
g_return_if_fail (pcall != NULL);
for (elt = self->priv->pcalls; elt; elt = g_slist_next (elt)) { for (elt = pcall_list; elt; elt = g_slist_next (elt)) {
if (pcall == elt->data) if (pcall == elt->data)
return; return pcall_list;
} }
self->priv->pcalls = g_slist_append (self->priv->pcalls, pcall); return g_slist_append (pcall_list, pcall);
} }
static void static GSList *
remove_pcall (NMSupplicantInterface * self, pcall_list_remove_pcall (GSList * pcall_list,
DBusPendingCall * pcall) DBusPendingCall * pcall)
{ {
GSList * elt; GSList * elt;
g_return_if_fail (self != NULL); g_return_val_if_fail (pcall != NULL, pcall_list);
g_return_if_fail (pcall != NULL);
for (elt = self->priv->pcalls; elt; elt = g_slist_next (elt)) { for (elt = pcall_list; elt; elt = g_slist_next (elt)) {
DBusPendingCall * list_pcall = (DBusPendingCall *) elt->data; DBusPendingCall * item = (DBusPendingCall *) elt->data;
if (list_pcall == pcall) { if (item == pcall) {
if (!dbus_pending_call_get_completed (pcall)) if (!dbus_pending_call_get_completed (pcall))
dbus_pending_call_cancel (pcall); dbus_pending_call_cancel (pcall);
self->priv->pcalls = g_slist_remove_link (self->priv->pcalls, elt); dbus_pending_call_unref (pcall);
pcall_list = g_slist_remove_link (pcall_list, elt);
g_slist_free_1 (elt); g_slist_free_1 (elt);
return; goto out;
}
} }
} }
static void out:
clear_pcalls (NMSupplicantInterface * self) return pcall_list;
}
static GSList *
pcall_list_clear (GSList * pcall_list)
{ {
GSList * elt; GSList * elt;
g_return_if_fail (self != NULL); for (elt = pcall_list; elt; elt = g_slist_next (elt)) {
for (elt = self->priv->pcalls; elt; elt = g_slist_next (elt)) {
DBusPendingCall * pcall = (DBusPendingCall *) elt->data; DBusPendingCall * pcall = (DBusPendingCall *) elt->data;
if (!dbus_pending_call_get_completed (pcall)) if (!dbus_pending_call_get_completed (pcall))
dbus_pending_call_cancel (pcall); dbus_pending_call_cancel (pcall);
dbus_pending_call_unref (pcall); dbus_pending_call_unref (pcall);
} }
g_slist_free (self->priv->pcalls); g_slist_free (pcall_list);
self->priv->pcalls = NULL; return NULL;
} }
@@ -197,7 +200,8 @@ nm_supplicant_interface_init (NMSupplicantInterface * self)
self->priv->smgr = NULL; self->priv->smgr = NULL;
self->priv->dev = NULL; self->priv->dev = NULL;
self->priv->wpas_iface_op = NULL; self->priv->wpas_iface_op = NULL;
self->priv->pcalls = NULL; self->priv->assoc_pcalls = NULL;
self->priv->other_pcalls = NULL;
self->priv->dispose_has_run = FALSE; self->priv->dispose_has_run = FALSE;
self->priv->dbus_mgr = nm_dbus_manager_get (NULL); self->priv->dbus_mgr = nm_dbus_manager_get (NULL);
@@ -306,7 +310,8 @@ nm_supplicant_interface_dispose (GObject *object)
} }
/* Cancel pending calls before unrefing the dbus manager */ /* Cancel pending calls before unrefing the dbus manager */
clear_pcalls (self); self->priv->other_pcalls = pcall_list_clear (self->priv->other_pcalls);
self->priv->assoc_pcalls = pcall_list_clear (self->priv->assoc_pcalls);
if (self->priv->dbus_mgr) { if (self->priv->dbus_mgr) {
if (self->priv->wpas_sig_handler_id) { if (self->priv->wpas_sig_handler_id) {
@@ -337,11 +342,15 @@ nm_supplicant_interface_finalize (GObject *object)
NMSupplicantInterfaceClass * klass; NMSupplicantInterfaceClass * klass;
GObjectClass * parent_class; GObjectClass * parent_class;
if (self->priv->wpas_iface_op) if (self->priv->wpas_iface_op) {
g_free (self->priv->wpas_iface_op); g_free (self->priv->wpas_iface_op);
self->priv->wpas_iface_op = NULL;
}
if (self->priv->wpas_net_op) if (self->priv->wpas_net_op) {
g_free (self->priv->wpas_net_op); g_free (self->priv->wpas_net_op);
self->priv->wpas_net_op = NULL;
}
/* Chain up to the parent class */ /* Chain up to the parent class */
klass = NM_SUPPLICANT_INTERFACE_CLASS (g_type_class_peek (NM_TYPE_SUPPLICANT_INTERFACE)); klass = NM_SUPPLICANT_INTERFACE_CLASS (g_type_class_peek (NM_TYPE_SUPPLICANT_INTERFACE));
@@ -439,6 +448,16 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
nm_supplicant_marshal_VOID__UINT_UINT, nm_supplicant_marshal_VOID__UINT_UINT,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
klass->connection_state = NULL; klass->connection_state = NULL;
nm_supplicant_interface_signals[CONNECTION_ERROR] =
g_signal_new ("connection-error",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMSupplicantInterfaceClass, connection_error),
NULL, NULL,
nm_supplicant_marshal_VOID__CHAR_CHAR,
G_TYPE_NONE, 2, G_TYPE_CHAR, G_TYPE_CHAR);
klass->connection_error = NULL;
} }
GType GType
@@ -466,6 +485,22 @@ nm_supplicant_interface_get_type (void)
return type; return type;
} }
static void
emit_error_helper (NMSupplicantInterface * self,
const char * name,
const char * message)
{
g_return_if_fail (self != NULL);
g_return_if_fail (name != NULL);
g_return_if_fail (message != NULL);
g_signal_emit (G_OBJECT (self),
nm_supplicant_interface_signals[CONNECTION_ERROR],
0,
name,
message);
}
static void static void
set_wpas_iface_op_from_message (NMSupplicantInterface * self, set_wpas_iface_op_from_message (NMSupplicantInterface * self,
@@ -535,7 +570,7 @@ out:
dbus_message_unref (reply); dbus_message_unref (reply);
if (dbus_error_is_set (&error)) if (dbus_error_is_set (&error))
dbus_error_free (&error); dbus_error_free (&error);
remove_pcall (self, pcall); self->priv->other_pcalls = pcall_list_remove_pcall (self->priv->other_pcalls, pcall);
} }
static void static void
@@ -574,7 +609,7 @@ request_bssid_properties (NMSupplicantInterface * self,
nm_warning ("could not send dbus message."); nm_warning ("could not send dbus message.");
goto out; goto out;
} }
add_pcall (self, pcall); self->priv->other_pcalls = pcall_list_add_pcall (self->priv->other_pcalls, pcall);
out: out:
if (message) if (message)
@@ -631,7 +666,7 @@ out:
dbus_message_unref (reply); dbus_message_unref (reply);
if (dbus_error_is_set (&error)) if (dbus_error_is_set (&error))
dbus_error_free (&error); dbus_error_free (&error);
remove_pcall (self, pcall); self->priv->other_pcalls = pcall_list_remove_pcall (self->priv->other_pcalls, pcall);
} }
static gboolean static gboolean
@@ -673,7 +708,7 @@ request_scan_results (gpointer user_data)
nm_warning ("could not send dbus message."); nm_warning ("could not send dbus message.");
goto out; goto out;
} }
add_pcall (self, pcall); self->priv->other_pcalls = pcall_list_add_pcall (self->priv->other_pcalls, pcall);
g_get_current_time (&cur_time); g_get_current_time (&cur_time);
self->priv->last_scan = cur_time.tv_sec; self->priv->last_scan = cur_time.tv_sec;
@@ -836,11 +871,22 @@ iface_state_cb (DBusPendingCall * pcall,
if (!(reply = dbus_pending_call_steal_reply (pcall))) if (!(reply = dbus_pending_call_steal_reply (pcall)))
goto out; goto out;
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
if (!dbus_set_error_from_message (&error, reply)) {
nm_warning ("couldn't get error information.");
} else {
nm_warning ("could not get interface state: %s - %s.",
error.name,
error.message);
}
goto out;
}
if (!dbus_message_get_args (reply, if (!dbus_message_get_args (reply,
&error, &error,
DBUS_TYPE_STRING, &state_str, DBUS_TYPE_STRING, &state_str,
DBUS_TYPE_INVALID)) { DBUS_TYPE_INVALID)) {
nm_warning ("could not get scan results: %s - %s.", nm_warning ("could not get interface state: %s - %s.",
error.name, error.name,
error.message); error.message);
goto out; goto out;
@@ -854,7 +900,7 @@ out:
dbus_message_unref (reply); dbus_message_unref (reply);
if (dbus_error_is_set (&error)) if (dbus_error_is_set (&error))
dbus_error_free (&error); dbus_error_free (&error);
remove_pcall (self, pcall); self->priv->other_pcalls = pcall_list_remove_pcall (self->priv->other_pcalls, pcall);
} }
static void static void
@@ -894,7 +940,7 @@ wpas_iface_get_state (NMSupplicantInterface *self)
nm_warning ("could not send dbus message."); nm_warning ("could not send dbus message.");
goto out; goto out;
} }
add_pcall (self, pcall); self->priv->other_pcalls = pcall_list_add_pcall (self->priv->other_pcalls, pcall);
out: out:
if (message) if (message)
@@ -962,7 +1008,7 @@ out:
dbus_message_unref (reply); dbus_message_unref (reply);
if (dbus_error_is_set (&error)) if (dbus_error_is_set (&error))
dbus_error_free (&error); dbus_error_free (&error);
remove_pcall (self, pcall); self->priv->other_pcalls = pcall_list_remove_pcall (self->priv->other_pcalls, pcall);
} }
@@ -1034,7 +1080,7 @@ nm_supplicant_interface_add_to_supplicant (NMSupplicantInterface * self,
nm_warning ("could not send dbus message."); nm_warning ("could not send dbus message.");
goto out; goto out;
} }
add_pcall (self, pcall); self->priv->other_pcalls = pcall_list_add_pcall (self->priv->other_pcalls, pcall);
out: out:
if (message) if (message)
@@ -1107,7 +1153,8 @@ nm_supplicant_interface_set_state (NMSupplicantInterface * self,
/* If the interface is transitioning to DOWN and there's are /* If the interface is transitioning to DOWN and there's are
* in-progress pending calls, cancel them. * in-progress pending calls, cancel them.
*/ */
clear_pcalls (self); self->priv->other_pcalls = pcall_list_clear (self->priv->other_pcalls);
self->priv->assoc_pcalls = pcall_list_clear (self->priv->assoc_pcalls);
} }
self->priv->state = new_state; self->priv->state = new_state;
@@ -1144,56 +1191,498 @@ nm_supplicant_interface_smgr_state_changed (NMSupplicantManager * smgr,
} }
} }
#if 0
static void static void
add_config_to_iface (NMSupplicantInterface *self) remove_network_cb (DBusPendingCall * pcall,
NMSupplicantInterface * self)
{
DBusError error;
DBusMessage * reply = NULL;
g_return_if_fail (pcall != NULL);
g_return_if_fail (self != NULL);
dbus_error_init (&error);
nm_dbus_send_with_callback_replied (pcall, __func__);
if (!dbus_pending_call_get_completed (pcall))
goto out;
if (!(reply = dbus_pending_call_steal_reply (pcall)))
goto out;
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
dbus_set_error_from_message (&error, reply);
nm_warning ("Couldn't remove network from supplicant interface: %s - %s",
error.name,
error.message);
}
out:
if (reply)
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
self->priv->other_pcalls = pcall_list_remove_pcall (self->priv->other_pcalls, pcall);
}
static void
disconnect_cb (DBusPendingCall * pcall,
NMSupplicantInterface * self)
{
DBusError error;
DBusMessage * reply = NULL;
g_return_if_fail (pcall != NULL);
g_return_if_fail (self != NULL);
dbus_error_init (&error);
nm_dbus_send_with_callback_replied (pcall, __func__);
if (!dbus_pending_call_get_completed (pcall))
goto out;
if (!(reply = dbus_pending_call_steal_reply (pcall)))
goto out;
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
dbus_set_error_from_message (&error, reply);
nm_warning ("Couldn't disconnect supplicant interface: %s - %s",
error.name,
error.message);
}
out:
if (reply)
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
self->priv->other_pcalls = pcall_list_remove_pcall (self->priv->other_pcalls, pcall);
}
void
nm_supplicant_interface_disconnect (NMSupplicantInterface * self)
{ {
DBusConnection * dbus_connection;
DBusMessage * message = NULL; DBusMessage * message = NULL;
DBusPendingCall * pcall = NULL; DBusPendingCall * pcall = NULL;
DBusConnection * dbus_connection;
g_return_if_fail (self != NULL); g_return_if_fail (self != NULL);
/* Clear and cancel all pending calls related to a prior
* connection attempt.
*/
self->priv->assoc_pcalls = pcall_list_clear (self->priv->assoc_pcalls);
/* Don't do anything if there is no connection to the supplicant yet. */
if (!self->priv->wpas_iface_op)
return;
dbus_connection = nm_dbus_manager_get_dbus_connection (self->priv->dbus_mgr); dbus_connection = nm_dbus_manager_get_dbus_connection (self->priv->dbus_mgr);
if (!dbus_connection) { if (!dbus_connection) {
nm_warning ("could not get the dbus connection."); nm_warning ("could not get the dbus connection.");
goto out; goto out;
} }
/* Don't try to disconnect if the supplicant interface is already
* disconnected.
*/
if (self->priv->con_state != NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED
&& self->priv->con_state != NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE) {
if (self->priv->wpas_net_op) {
g_free (self->priv->wpas_net_op);
self->priv->wpas_net_op = NULL;
}
return;
}
/* Remove any network that was added by NetworkManager */
if (self->priv->wpas_net_op) {
message = dbus_message_new_method_call (WPAS_DBUS_SERVICE, message = dbus_message_new_method_call (WPAS_DBUS_SERVICE,
WPAS_DBUS_IFACE_INTERFACE,
self->priv->wpas_iface_op, self->priv->wpas_iface_op,
"addNetwork"); WPAS_DBUS_IFACE_INTERFACE,
"removeNetwork");
if (!message) { if (!message) {
nm_warning ("Couldn't create dbus message."); nm_warning ("Couldn't create dbus message.");
goto out; goto out;
} }
#if 0 if (!dbus_message_append_args (message,
DBUS_TYPE_OBJECT_PATH, &self->priv->wpas_net_op,
DBUS_TYPE_INVALID)) {
nm_warning ("Couldn't compose removeNetwork dbus message.");
goto out;
}
pcall = nm_dbus_send_with_callback (dbus_connection, pcall = nm_dbus_send_with_callback (dbus_connection,
message, message,
(DBusPendingCallNotifyFunction) nm_supplicant_interface_add_config_cb, (DBusPendingCallNotifyFunction) remove_network_cb,
self,
NULL,
__func__);
dbus_message_unref (message);
g_free (self->priv->wpas_net_op);
self->priv->wpas_net_op = NULL;
}
/* Send a general disconnect command */
message = dbus_message_new_method_call (WPAS_DBUS_SERVICE,
self->priv->wpas_iface_op,
WPAS_DBUS_IFACE_INTERFACE,
"disconnect");
if (!message) {
nm_warning ("Couldn't create dbus message.");
goto out;
}
pcall = nm_dbus_send_with_callback (dbus_connection,
message,
(DBusPendingCallNotifyFunction) disconnect_cb,
self, self,
NULL, NULL,
__func__); __func__);
#endif
out: out:
; if (message)
dbus_message_unref (message);
} }
#endif
void #define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network"
static void
select_network_cb (DBusPendingCall * pcall,
NMSupplicantInterface * self)
{
DBusError error;
DBusMessage * reply = NULL;
g_return_if_fail (pcall != NULL);
g_return_if_fail (self != NULL);
dbus_error_init (&error);
nm_dbus_send_with_callback_replied (pcall, __func__);
if (!dbus_pending_call_get_completed (pcall)) {
emit_error_helper (self, "SelectNetworkError", "pending call not yet completed");
goto out;
}
if (!(reply = dbus_pending_call_steal_reply (pcall))) {
emit_error_helper (self, "SelectNetworkError", "could not steal reply");
goto out;
}
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
dbus_set_error_from_message (&error, reply);
nm_warning ("Couldn't select network config: %s - %s",
error.name,
error.message);
emit_error_helper (self, error.name, error.message);
goto out;
}
out:
if (reply)
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
self->priv->assoc_pcalls = pcall_list_remove_pcall (self->priv->assoc_pcalls, pcall);
}
static void
set_network_cb (DBusPendingCall * pcall,
NMSupplicantInterface * self)
{
DBusError error;
DBusMessage * reply = NULL;
DBusConnection * dbus_connection;
DBusMessage * message = NULL;
g_return_if_fail (pcall != NULL);
g_return_if_fail (self != NULL);
dbus_connection = nm_dbus_manager_get_dbus_connection (self->priv->dbus_mgr);
if (!dbus_connection) {
nm_warning ("could not get the dbus connection.");
emit_error_helper (self, "SetNetworkError", "could not get the dbus connection.");
goto out;
}
dbus_error_init (&error);
nm_dbus_send_with_callback_replied (pcall, __func__);
if (!dbus_pending_call_get_completed (pcall)) {
emit_error_helper (self, "SetNetworkError", "pending call not yet completed");
goto out;
}
if (!(reply = dbus_pending_call_steal_reply (pcall))) {
emit_error_helper (self, "SetNetworkError", "could not steal reply");
goto out;
}
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
dbus_set_error_from_message (&error, reply);
nm_warning ("Couldn't set network config: %s - %s",
error.name,
error.message);
emit_error_helper (self, error.name, error.message);
goto out;
}
message = dbus_message_new_method_call (WPAS_DBUS_SERVICE,
self->priv->wpas_iface_op,
WPAS_DBUS_IFACE_INTERFACE,
"selectNetwork");
if (!message) {
nm_warning ("Couldn't create dbus message.");
emit_error_helper (self, "SetNetworkError", "could not create dbus message.");
goto out;
}
if (!dbus_message_append_args (message,
DBUS_TYPE_OBJECT_PATH, &self->priv->wpas_net_op,
DBUS_TYPE_INVALID)) {
emit_error_helper (self, "SetNetworkError", "could not add arguments to message.");
goto out;
}
nm_dbus_send_with_callback (dbus_connection,
message,
(DBusPendingCallNotifyFunction) select_network_cb,
self,
NULL,
__func__);
out:
if (reply)
dbus_message_unref (reply);
if (message)
dbus_message_unref (message);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
self->priv->assoc_pcalls = pcall_list_remove_pcall (self->priv->assoc_pcalls, pcall);
}
static void
add_network_cb (DBusPendingCall * pcall,
NMSupplicantInterface * self)
{
DBusError error;
DBusMessage * reply = NULL;
DBusMessage * message = NULL;
DBusConnection * dbus_connection = NULL;
char * net_op = NULL;
g_return_if_fail (pcall != NULL);
g_return_if_fail (self != NULL);
dbus_connection = nm_dbus_manager_get_dbus_connection (self->priv->dbus_mgr);
if (!dbus_connection) {
nm_warning ("could not get the dbus connection.");
emit_error_helper (self, "AddNetworkError", "could not get the dbus connection.");
goto out;
}
dbus_error_init (&error);
nm_dbus_send_with_callback_replied (pcall, __func__);
if (!dbus_pending_call_get_completed (pcall)) {
emit_error_helper (self, "AddNetworkError", "pending call not yet completed.");
goto out;
}
if (!(reply = dbus_pending_call_steal_reply (pcall))) {
emit_error_helper (self, "AddNetworkError", "could not steal reply");
goto out;
}
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
dbus_set_error_from_message (&error, reply);
nm_warning ("Couldn't add a network to the supplicant interface: %s - %s",
error.name,
error.message);
emit_error_helper (self, error.name, error.message);
goto out;
}
if (!dbus_message_get_args (reply,
&error,
DBUS_TYPE_OBJECT_PATH, &net_op,
DBUS_TYPE_INVALID)) {
nm_warning ("couldn't get network object path from the supplicant: %s - %s",
error.name,
error.message);
emit_error_helper (self, error.name, error.message);
goto out;
}
self->priv->wpas_net_op = g_strdup (net_op);
message = dbus_message_new_method_call (WPAS_DBUS_SERVICE,
self->priv->wpas_net_op,
WPAS_DBUS_IFACE_NETWORK,
"set");
if (!message) {
nm_warning ("Couldn't create dbus message.");
emit_error_helper (self, "AddNetworkError", "could not create dbus message.");
goto out;
}
if (!nm_supplicant_config_add_to_dbus_message (self->priv->cfg, message)) {
emit_error_helper (self, "AddNetworkError", "could not add config to dbus message.");
goto out;
}
nm_dbus_send_with_callback (dbus_connection,
message,
(DBusPendingCallNotifyFunction) set_network_cb,
self,
NULL,
__func__);
dbus_message_unref (message);
out:
if (reply)
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
self->priv->assoc_pcalls = pcall_list_remove_pcall (self->priv->assoc_pcalls, pcall);
}
static void
set_ap_scan_cb (DBusPendingCall * pcall,
NMSupplicantInterface * self)
{
DBusError error;
DBusMessage * reply = NULL;
DBusMessage * message = NULL;
DBusConnection * dbus_connection = NULL;
g_return_if_fail (pcall != NULL);
g_return_if_fail (self != NULL);
dbus_connection = nm_dbus_manager_get_dbus_connection (self->priv->dbus_mgr);
if (!dbus_connection) {
nm_warning ("could not get the dbus connection.");
emit_error_helper (self, "SetAPScanError", "could not get the dbus connection.");
goto out;
}
dbus_error_init (&error);
nm_dbus_send_with_callback_replied (pcall, __func__);
if (!dbus_pending_call_get_completed (pcall)) {
emit_error_helper (self, "SetAPScanError", "pending call not yet completed.");
goto out;
}
if (!(reply = dbus_pending_call_steal_reply (pcall))) {
emit_error_helper (self, "SetAPScanError", "could not steal reply");
goto out;
}
if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR) {
dbus_set_error_from_message (&error, reply);
nm_warning ("Couldn't send AP scan mode to the supplicant interface: %s - %s",
error.name,
error.message);
emit_error_helper (self, error.name, error.message);
goto out;
}
message = dbus_message_new_method_call (WPAS_DBUS_SERVICE,
self->priv->wpas_iface_op,
WPAS_DBUS_IFACE_INTERFACE,
"addNetwork");
if (!message) {
nm_warning ("Couldn't create dbus message.");
emit_error_helper (self, "SetAPScanError", "couldn't create addNetwork message");
goto out;
}
pcall = nm_dbus_send_with_callback (dbus_connection,
message,
(DBusPendingCallNotifyFunction) add_network_cb,
self,
NULL,
__func__);
out:
if (reply)
dbus_message_unref (reply);
if (dbus_error_is_set (&error))
dbus_error_free (&error);
self->priv->assoc_pcalls = pcall_list_remove_pcall (self->priv->assoc_pcalls, pcall);
}
#include <stdio.h>
gboolean
nm_supplicant_interface_set_config (NMSupplicantInterface * self, nm_supplicant_interface_set_config (NMSupplicantInterface * self,
NMSupplicantConfig * cfg) NMSupplicantConfig * cfg)
{ {
g_return_if_fail (self != NULL); DBusConnection * dbus_connection;
DBusMessage * message = NULL;
DBusPendingCall * pcall = NULL;
gboolean success = FALSE;
guint32 ap_scan;
g_return_val_if_fail (self != NULL, FALSE);
dbus_connection = nm_dbus_manager_get_dbus_connection (self->priv->dbus_mgr);
if (!dbus_connection) {
nm_warning ("could not get the dbus connection.");
goto out;
}
nm_supplicant_interface_disconnect (self);
if (self->priv->cfg) if (self->priv->cfg)
g_object_unref (self->priv->cfg); g_object_unref (self->priv->cfg);
self->priv->cfg = cfg; self->priv->cfg = cfg;
if (self->priv->cfg)
if (cfg == NULL) {
success = TRUE;
goto out;
}
g_object_ref (self->priv->cfg); g_object_ref (self->priv->cfg);
message = dbus_message_new_method_call (WPAS_DBUS_SERVICE,
self->priv->wpas_iface_op,
WPAS_DBUS_IFACE_INTERFACE,
"setAPScan");
if (!message) {
nm_warning ("Couldn't create dbus message.");
goto out;
}
ap_scan = nm_supplicant_config_get_ap_scan (self->priv->cfg);
if (!dbus_message_append_args (message,
DBUS_TYPE_UINT32, &ap_scan,
DBUS_TYPE_INVALID))
{
nm_warning ("couldn't set ap scan message arguments.");
goto out;
}
pcall = nm_dbus_send_with_callback (dbus_connection,
message,
(DBusPendingCallNotifyFunction) set_ap_scan_cb,
self,
NULL,
__func__);
success = TRUE;
out:
if (message)
dbus_message_unref (message);
return success;
} }
NMDevice * NMDevice *
@@ -1249,7 +1738,7 @@ out:
dbus_message_unref (reply); dbus_message_unref (reply);
if (dbus_error_is_set (&error)) if (dbus_error_is_set (&error))
dbus_error_free (&error); dbus_error_free (&error);
remove_pcall (self, pcall); self->priv->other_pcalls = pcall_list_remove_pcall (self->priv->other_pcalls, pcall);
} }
gboolean gboolean
@@ -1288,7 +1777,7 @@ nm_supplicant_interface_request_scan (NMSupplicantInterface * self)
nm_warning ("could not send dbus message."); nm_warning ("could not send dbus message.");
goto out; goto out;
} }
add_pcall (self, pcall); self->priv->other_pcalls = pcall_list_add_pcall (self->priv->other_pcalls, pcall);
success = TRUE; success = TRUE;
out: out:

View File

@@ -109,6 +109,10 @@ struct _NMSupplicantInterfaceClass
void (* connection_state) (NMSupplicantInterface * iface, void (* connection_state) (NMSupplicantInterface * iface,
guint32 new_state, guint32 new_state,
guint32 old_state); guint32 old_state);
void (* connection_error) (NMSupplicantInterface * iface,
const char * name,
const char * message);
}; };
@@ -117,9 +121,11 @@ GType nm_supplicant_interface_get_type (void);
NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager * smgr, NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager * smgr,
NMDevice * dev); NMDevice * dev);
void nm_supplicant_interface_set_config (NMSupplicantInterface * iface, gboolean nm_supplicant_interface_set_config (NMSupplicantInterface * iface,
NMSupplicantConfig * cfg); NMSupplicantConfig * cfg);
void nm_supplicant_interface_disconnect (NMSupplicantInterface * iface);
NMDevice * nm_supplicant_interface_get_device (NMSupplicantInterface * iface); NMDevice * nm_supplicant_interface_get_device (NMSupplicantInterface * iface);
gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self); gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self);

View File

@@ -1 +1,2 @@
VOID:UINT,UINT VOID:UINT,UINT
VOID:CHAR,CHAR

View File

@@ -27,36 +27,38 @@
#include "nm-supplicant-settings-verify.h" #include "nm-supplicant-settings-verify.h"
enum OptType {
TYPE_INT = 0,
TYPE_STRING,
TYPE_KEYWORD
};
struct Opt { struct Opt {
const char * key; const char * key;
const enum OptType type; const OptType type;
const gint32 int_low; /* Inclusive */ const gint32 int_low; /* Inclusive */
const gint32 int_high; /* Inclusive */ const gint32 int_high; /* Inclusive; max length for strings */
const gboolean str_allowed_multiple; const gboolean str_allowed_multiple;
const char ** str_allowed; const char ** str_allowed;
}; };
static gboolean validate_type_int (const struct Opt * opt, const char * value); static gboolean validate_type_int (const struct Opt * opt,
static gboolean validate_type_string (const struct Opt * opt, const char * value); const char * value,
static gboolean validate_type_keyword (const struct Opt * opt, const char * value); const guint32 len);
typedef gboolean (*validate_func)(const struct Opt *, const char *); static gboolean validate_type_bytes (const struct Opt * opt,
const char * value,
const guint32 len);
static gboolean validate_type_keyword (const struct Opt * opt,
const char * value,
const guint32 len);
typedef gboolean (*validate_func)(const struct Opt *, const char *, const guint32);
struct validate_entry { struct validate_entry {
const enum OptType type; const OptType type;
const validate_func func; const validate_func func;
}; };
static const struct validate_entry validate_table[] = { static const struct validate_entry validate_table[] = {
{ TYPE_INT, validate_type_int }, { TYPE_INT, validate_type_int },
{ TYPE_STRING, validate_type_string }, { TYPE_BYTES, validate_type_bytes },
{ TYPE_KEYWORD, validate_type_keyword }, { TYPE_KEYWORD, validate_type_keyword },
}; };
@@ -76,49 +78,51 @@ const char * phase2_allowed[] = {"auth=MSCHAPV2", "auth=PAP", "autheap=TLS",
"autheap=MSCHAPV2", "autheap=MD5", NULL }; "autheap=MSCHAPV2", "autheap=MD5", NULL };
static const struct Opt opt_table[] = { static const struct Opt opt_table[] = {
{ "ssid", TYPE_STRING, 0, 0, FALSE, NULL }, { "ssid", TYPE_BYTES, 0, 32,FALSE, NULL },
{ "bssid", TYPE_STRING, 0, 0, FALSE, NULL }, { "bssid", TYPE_BYTES, 0, 6, FALSE, NULL },
{ "scan_ssid", TYPE_INT, 0, 1, FALSE, NULL }, { "scan_ssid", TYPE_INT, 0, 1, FALSE, NULL },
{ "mode", TYPE_INT, 0, 1, FALSE, NULL }, { "mode", TYPE_INT, 0, 1, FALSE, NULL },
{ "auth_alg", TYPE_KEYWORD, 0, 0, FALSE, auth_alg_allowed }, { "auth_alg", TYPE_KEYWORD, 0, 0, FALSE, auth_alg_allowed },
{ "psk", TYPE_STRING, 0, 0, FALSE, NULL }, { "psk", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "pairwise", TYPE_KEYWORD, 0, 0, FALSE, pairwise_allowed }, { "pairwise", TYPE_KEYWORD, 0, 0, FALSE, pairwise_allowed },
{ "group", TYPE_KEYWORD, 0, 0, FALSE, group_allowed }, { "group", TYPE_KEYWORD, 0, 0, FALSE, group_allowed },
{ "proto", TYPE_KEYWORD, 0, 0, FALSE, proto_allowed }, { "proto", TYPE_KEYWORD, 0, 0, FALSE, proto_allowed },
{ "key_mgmt", TYPE_KEYWORD, 0, 0, FALSE, key_mgmt_allowed }, { "key_mgmt", TYPE_KEYWORD, 0, 0, FALSE, key_mgmt_allowed },
{ "wep_key0", TYPE_STRING, 0, 0, FALSE, NULL }, { "wep_key0", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "wep_key1", TYPE_STRING, 0, 0, FALSE, NULL }, { "wep_key1", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "wep_key2", TYPE_STRING, 0, 0, FALSE, NULL }, { "wep_key2", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "wep_key3", TYPE_STRING, 0, 0, FALSE, NULL }, { "wep_key3", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "wep_tx_keyidx", TYPE_INT, 0, 3, FALSE, NULL }, { "wep_tx_keyidx", TYPE_INT, 0, 3, FALSE, NULL },
{ "eapol_flags", TYPE_INT, 0, 3, FALSE, NULL }, { "eapol_flags", TYPE_INT, 0, 3, FALSE, NULL },
{ "eap", TYPE_KEYWORD, 0, 0, FALSE, eap_allowed }, { "eap", TYPE_KEYWORD, 0, 0, FALSE, eap_allowed },
{ "identity", TYPE_STRING, 0, 0, FALSE, NULL }, { "identity", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "password", TYPE_STRING, 0, 0, FALSE, NULL }, { "password", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "ca_cert", TYPE_STRING, 0, 0, FALSE, NULL }, { "ca_cert", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "client_cert", TYPE_STRING, 0, 0, FALSE, NULL }, { "client_cert", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "private_key", TYPE_STRING, 0, 0, FALSE, NULL }, { "private_key", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "private_key_passwd", TYPE_STRING, 0, 0, FALSE, NULL }, { "private_key_passwd", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "phase1", TYPE_KEYWORD, 0, 0, TRUE, phase1_allowed }, { "phase1", TYPE_KEYWORD, 0, 0, TRUE, phase1_allowed },
{ "phase2", TYPE_KEYWORD, 0, 0, TRUE, phase2_allowed }, { "phase2", TYPE_KEYWORD, 0, 0, TRUE, phase2_allowed },
{ "anonymous_identity", TYPE_STRING, 0, 0, FALSE, NULL }, { "anonymous_identity", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "ca_cert2", TYPE_STRING, 0, 0, FALSE, NULL }, { "ca_cert2", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "client_cert2", TYPE_STRING, 0, 0, FALSE, NULL }, { "client_cert2", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "private_key2", TYPE_STRING, 0, 0, FALSE, NULL }, { "private_key2", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "private_key2_passwd",TYPE_STRING, 0, 0, FALSE, NULL }, { "private_key2_passwd",TYPE_BYTES, 0, 0, FALSE, NULL },
{ "pin", TYPE_STRING, 0, 0, FALSE, NULL }, { "pin", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "pcsc", TYPE_STRING, 0, 0, FALSE, NULL }, { "pcsc", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "nai", TYPE_STRING, 0, 0, FALSE, NULL }, { "nai", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "eappsk", TYPE_STRING, 0, 0, FALSE, NULL }, { "eappsk", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "pac_file", TYPE_STRING, 0, 0, FALSE, NULL }, { "pac_file", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "engine", TYPE_INT, 0, 1, FALSE, NULL }, { "engine", TYPE_INT, 0, 1, FALSE, NULL },
{ "engine_id", TYPE_STRING, 0, 0, FALSE, NULL }, { "engine_id", TYPE_BYTES, 0, 0, FALSE, NULL },
{ "key_id", TYPE_STRING, 0, 0, FALSE, NULL }, { "key_id", TYPE_BYTES, 0, 0, FALSE, NULL },
}; };
static gboolean static gboolean
validate_type_int (const struct Opt * opt, const char * value) validate_type_int (const struct Opt * opt,
const char * value,
const guint32 len)
{ {
long int intval; long int intval;
@@ -140,20 +144,26 @@ validate_type_int (const struct Opt * opt, const char * value)
} }
static gboolean static gboolean
validate_type_string (const struct Opt * opt, const char * value) validate_type_bytes (const struct Opt * opt,
const char * value,
const guint32 len)
{ {
guint32 check_len;
g_return_val_if_fail (opt != NULL, FALSE); g_return_val_if_fail (opt != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE);
/* FIXME: what can we do with a string other than length? */ check_len = opt->int_high ? opt->int_high : 255;
if (strlen (value) > PATH_MAX) if (len > check_len)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
static gboolean static gboolean
validate_type_keyword (const struct Opt * opt, const char * value) validate_type_keyword (const struct Opt * opt,
const char * value,
const guint32 len)
{ {
char ** allowed; char ** allowed;
gchar ** candidates = NULL; gchar ** candidates = NULL;
@@ -168,7 +178,8 @@ validate_type_keyword (const struct Opt * opt, const char * value)
goto out; goto out;
/* validate each space-separated word in 'value' */ /* validate each space-separated word in 'value' */
for (candidate = candidates; *candidate; candidate++, found = FALSE) { for (candidate = candidates; *candidate; candidate++) {
found = FALSE;
for (allowed = (char **) opt->str_allowed; *allowed; allowed++) { for (allowed = (char **) opt->str_allowed; *allowed; allowed++) {
if (strcmp (*candidate, *allowed) == 0) { if (strcmp (*candidate, *allowed) == 0) {
found = TRUE; found = TRUE;
@@ -184,11 +195,12 @@ out:
return found; return found;
} }
gboolean OptType
nm_supplicant_settings_verify_setting (const char * key, nm_supplicant_settings_verify_setting (const char * key,
const char * value) const char * value,
const guint32 len)
{ {
gboolean valid = FALSE; OptType type = TYPE_INVALID;
int opt_count = sizeof (opt_table) / sizeof (opt_table[0]); int opt_count = sizeof (opt_table) / sizeof (opt_table[0]);
int val_count = sizeof (validate_table) / sizeof (validate_table[0]); int val_count = sizeof (validate_table) / sizeof (validate_table[0]);
int i, j; int i, j;
@@ -196,17 +208,20 @@ nm_supplicant_settings_verify_setting (const char * key,
g_return_val_if_fail (key != NULL, FALSE); g_return_val_if_fail (key != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE);
for (i = 0; i < opt_count && !valid; i++) { for (i = 0; i < opt_count; i++) {
if (strcmp (opt_table[i].key, key) != 0) if (strcmp (opt_table[i].key, key) != 0)
continue; continue;
for (j = 0; j < val_count; j++) { for (j = 0; j < val_count; j++) {
if (validate_table[j].type == opt_table[i].type) { if (validate_table[j].type == opt_table[i].type) {
valid = (*(validate_table[j].func))(&opt_table[i], value); if ((*(validate_table[j].func))(&opt_table[i], value, len)) {
type = opt_table[i].type;
break; break;
} }
} }
} }
return valid;
} }
return type;
}

View File

@@ -22,10 +22,16 @@
#ifndef NM_SUPPLICANT_SETTINGS_VERIFY_H #ifndef NM_SUPPLICANT_SETTINGS_VERIFY_H
#define NM_SUPPLICANT_SETTINGS_VERIFY_H #define NM_SUPPLICANT_SETTINGS_VERIFY_H
gboolean nm_supplicant_settings_verify_setting (const char * key, typedef enum OptType {
const char * value); TYPE_INVALID = 0,
TYPE_INT,
TYPE_BYTES,
TYPE_KEYWORD
} OptType;
OptType nm_supplicant_settings_verify_setting (const char * key,
const char * value,
const guint32 len);
#endif /* NM_SUPPLICANT_SETTINGS_VERIFY_H */ #endif /* NM_SUPPLICANT_SETTINGS_VERIFY_H */

View File

@@ -1,240 +0,0 @@
/*
* wpa_supplicant/hostapd control interface library
* Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* 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.
*/
/* WHACK #include "includes.h" */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#define CONFIG_CTRL_IFACE
#ifdef CONFIG_CTRL_IFACE
#ifndef CONFIG_CTRL_IFACE_UDP
#include <sys/un.h>
#endif /* CONFIG_CTRL_IFACE_UDP */
#include "wpa_ctrl.h"
/* WHACK #include "common.h" */
/**
* struct wpa_ctrl - Internal structure for control interface library
*
* This structure is used by the wpa_supplicant/hostapd control interface
* library to store internal data. Programs using the library should not touch
* this data directly. They can only use the pointer to the data structure as
* an identifier for the control interface connection and use this as one of
* the arguments for most of the control interface library functions.
*/
struct wpa_ctrl {
int s;
#ifdef CONFIG_CTRL_IFACE_UDP
struct sockaddr_in local;
struct sockaddr_in dest;
#else /* CONFIG_CTRL_IFACE_UDP */
struct sockaddr_un local;
struct sockaddr_un dest;
#endif /* CONFIG_CTRL_IFACE_UDP */
};
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path,
const char *local_path_dir)
{
struct wpa_ctrl *ctrl;
#ifndef CONFIG_CTRL_IFACE_UDP
static int counter = 0;
#endif /* CONFIG_CTRL_IFACE_UDP */
ctrl = malloc(sizeof(*ctrl));
if (ctrl == NULL)
return NULL;
memset(ctrl, 0, sizeof(*ctrl));
#ifdef CONFIG_CTRL_IFACE_UDP
ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
if (ctrl->s < 0) {
perror("socket");
free(ctrl);
return NULL;
}
ctrl->local.sin_family = AF_INET;
ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
sizeof(ctrl->local)) < 0) {
close(ctrl->s);
free(ctrl);
return NULL;
}
ctrl->dest.sin_family = AF_INET;
ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
perror("connect");
close(ctrl->s);
free(ctrl);
return NULL;
}
#else /* CONFIG_CTRL_IFACE_UDP */
ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
if (ctrl->s < 0) {
free(ctrl);
return NULL;
}
ctrl->local.sun_family = AF_UNIX;
snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
"%s/wpa_ctrl_%d-%d", local_path_dir, getpid(), counter++);
if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
sizeof(ctrl->local)) < 0) {
close(ctrl->s);
free(ctrl);
return NULL;
}
ctrl->dest.sun_family = AF_UNIX;
snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s",
ctrl_path);
if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
sizeof(ctrl->dest)) < 0) {
close(ctrl->s);
unlink(ctrl->local.sun_path);
free(ctrl);
return NULL;
}
#endif /* CONFIG_CTRL_IFACE_UDP */
return ctrl;
}
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
{
#ifndef CONFIG_CTRL_IFACE_UDP
unlink(ctrl->local.sun_path);
#endif /* CONFIG_CTRL_IFACE_UDP */
close(ctrl->s);
free(ctrl);
}
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len))
{
struct timeval tv;
int res;
fd_set rfds;
if (send(ctrl->s, cmd, cmd_len, 0) < 0)
return -1;
for (;;) {
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
if (FD_ISSET(ctrl->s, &rfds)) {
res = recv(ctrl->s, reply, *reply_len, 0);
if (res < 0)
return res;
if (res > 0 && reply[0] == '<') {
/* This is an unsolicited message from
* wpa_supplicant, not the reply to the
* request. Use msg_cb to report this to the
* caller. */
if (msg_cb) {
/* Make sure the message is nul
* terminated. */
if ((size_t) res == *reply_len)
res = (*reply_len) - 1;
reply[res] = '\0';
msg_cb(reply, res);
}
continue;
}
*reply_len = res;
break;
} else {
return -2;
}
}
return 0;
}
static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
{
char buf[10];
int ret;
size_t len = 10;
ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
buf, &len, NULL);
if (ret < 0)
return ret;
if (len == 3 && memcmp(buf, "OK\n", 3) == 0)
return 0;
return -1;
}
int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
{
return wpa_ctrl_attach_helper(ctrl, 1);
}
int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
{
return wpa_ctrl_attach_helper(ctrl, 0);
}
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
{
int res;
res = recv(ctrl->s, reply, *reply_len, 0);
if (res < 0)
return res;
*reply_len = res;
return 0;
}
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
{
struct timeval tv;
int res;
fd_set rfds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(ctrl->s, &rfds);
res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
return FD_ISSET(ctrl->s, &rfds);
}
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
{
return ctrl->s;
}
#endif /* CONFIG_CTRL_IFACE */

View File

@@ -1,185 +0,0 @@
/*
* wpa_supplicant/hostapd control interface library
* Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* 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.
*/
#ifndef WPA_CTRL_H
#define WPA_CTRL_H
#ifdef __cplusplus
extern "C" {
#endif
/* wpa_supplicant control interface - fixed message prefixes */
/** Interactive request for identity/password/pin */
#define WPA_CTRL_REQ "CTRL-REQ-"
/** Response to identity/password/pin request */
#define WPA_CTRL_RSP "CTRL-RSP-"
/* Event messages with fixed prefix */
/** Authentication completed successfully and data connection enabled */
#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED "
/** Disconnected, data connection is not available */
#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED "
/** wpa_supplicant is exiting */
#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
/** Password change was completed successfully */
#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED "
/** EAP-Request/Notification received */
#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION "
/** EAP authentication started (EAP-Request/Identity received) */
#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED "
/** EAP method selected */
#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD "
/** EAP authentication completed successfully */
#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS "
/** EAP authentication failed (EAP-Failure received) */
#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE "
/* wpa_supplicant/hostapd control interface access */
/**
* wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd
* @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used.
* Returns: Pointer to abstract control interface data or %NULL on failure
*
* This function is used to open a control interface to wpa_supplicant/hostapd.
* ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path
* is configured in wpa_supplicant/hostapd and other programs using the control
* interface need to use matching path configuration.
*/
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path, const char *local_path_dir);
/**
* wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd
* @ctrl: Control interface data from wpa_ctrl_open()
*
* This function is used to close a control interface.
*/
void wpa_ctrl_close(struct wpa_ctrl *ctrl);
/**
* wpa_ctrl_request - Send a command to wpa_supplicant/hostapd
* @ctrl: Control interface data from wpa_ctrl_open()
* @cmd: Command; usually, ASCII text, e.g., "PING"
* @cmd_len: Length of the cmd in bytes
* @reply: Buffer for the response
* @reply_len: Reply buffer length
* @msg_cb: Callback function for unsolicited messages or %NULL if not used
* Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout
*
* This function is used to send commands to wpa_supplicant/hostapd. Received
* response will be written to reply and reply_len is set to the actual length
* of the reply. This function will block for up to two seconds while waiting
* for the reply. If unsolicited messages are received, the blocking time may
* be longer.
*
* msg_cb can be used to register a callback function that will be called for
* unsolicited messages received while waiting for the command response. These
* messages may be received if wpa_ctrl_request() is called at the same time as
* wpa_supplicant/hostapd is sending such a message. This can happen only if
* the program has used wpa_ctrl_attach() to register itself as a monitor for
* event messages. Alternatively to msg_cb, programs can register two control
* interface connections and use one of them for commands and the other one for
* receiving event messages, in other words, call wpa_ctrl_attach() only for
* the control interface connection that will be used for event messages.
*/
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
char *reply, size_t *reply_len,
void (*msg_cb)(char *msg, size_t len));
/**
* wpa_ctrl_attach - Register as an event monitor for the control interface
* @ctrl: Control interface data from wpa_ctrl_open()
* Returns: 0 on success, -1 on failure, -2 on timeout
*
* This function registers the control interface connection as a monitor for
* wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the
* control interface connection starts receiving event messages that can be
* read with wpa_ctrl_recv().
*/
int wpa_ctrl_attach(struct wpa_ctrl *ctrl);
/**
* wpa_ctrl_detach - Unregister event monitor from the control interface
* @ctrl: Control interface data from wpa_ctrl_open()
* Returns: 0 on success, -1 on failure, -2 on timeout
*
* This function unregisters the control interface connection as a monitor for
* wpa_supplicant/hostapd events, i.e., cancels the registration done with
* wpa_ctrl_attach().
*/
int wpa_ctrl_detach(struct wpa_ctrl *ctrl);
/**
* wpa_ctrl_recv - Receive a pending control interface message
* @ctrl: Control interface data from wpa_ctrl_open()
* @reply: Buffer for the message data
* @reply_len: Length of the reply buffer
* Returns: 0 on success, -1 on failure
*
* This function will receive a pending control interface message. This
* function will block if no messages are available. The received response will
* be written to reply and reply_len is set to the actual length of the reply.
* wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach()
* must have been used to register the control interface as an event monitor.
*/
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len);
/**
* wpa_ctrl_pending - Check whether there are pending event messages
* @ctrl: Control interface data from wpa_ctrl_open()
* Returns: Non-zero if there are pending messages
*
* This function will check whether there are any pending control interface
* message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is
* only used for event messages, i.e., wpa_ctrl_attach() must have been used to
* register the control interface as an event monitor.
*/
int wpa_ctrl_pending(struct wpa_ctrl *ctrl);
/**
* wpa_ctrl_get_fd - Get file descriptor used by the control interface
* @ctrl: Control interface data from wpa_ctrl_open()
* Returns: File descriptor used for the connection
*
* This function can be used to get the file descriptor that is used for the
* control interface connection. The returned value can be used, e.g., with
* select() while waiting for multiple events.
*
* The returned file descriptor must not be used directly for sending or
* receiving packets; instead, the library functions wpa_ctrl_request() and
* wpa_ctrl_recv() must be used for this.
*/
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl);
#ifdef CONFIG_CTRL_IFACE_UDP
#define WPA_CTRL_IFACE_PORT 9877
#define WPA_GLOBAL_CTRL_IFACE_PORT 9878
#endif /* CONFIG_CTRL_IFACE_UDP */
#ifdef __cplusplus
}
#endif
#endif /* WPA_CTRL_H */