2006-01-04 Dan Williams <dcbw@redhat.com>

First dump of wpa_supplicant-related code.  It's not hooked up to
	anything yet though.  Thanks to Kay Sievers for
	wpa_supplicant_wrapper.c, which formed the basis for this work,
	and to Jouni Malinen for writing wpa_ctrl.c and wpa_ctrl.h.

	* src/Makefile.am
	  src/wpa_ctrl.[ch]
		- Add wpa_ctrl stuff from wpa_supplicant so we can talk to it

	* src/NetworkManagerUtils.[ch]
		- (nm_utils_supplicant_request, nm_utils_supplicant_request_with_check):
			Add convenience functions for talking to wpa_supplicant

	* src/nm-ap-security.[ch]
	  src/nm-ap-security-wep.c
	  src/nm-ap-security-wpa-psk.[ch]
		- Update and implement real_write_supplicant_config functions
			in all security types
		- (nm_ap_security_wpa_psk_new_from_ap): implement in
			nm-ap-security-wpa-psk.c

	* src/nm-device-802-11-wireless.c
		- (supplicant_cleanup, supplicant_watch_cb, supplicant_monitor_status_cb,
		   wpa_supplicant_start, wpa_supplicant_interface_init,
		   wpa_supplicant_send_network_config): add functions to talk to
			wpa_supplicant and write network config to it


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@1267 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2006-01-05 04:44:11 +00:00
parent eddd23576b
commit 9dcbf019bb
12 changed files with 946 additions and 33 deletions

View File

@@ -1,3 +1,32 @@
2006-01-04 Dan Williams <dcbw@redhat.com>
First dump of wpa_supplicant-related code. It's not hooked up to
anything yet though. Thanks to Kay Sievers for
wpa_supplicant_wrapper.c, which formed the basis for this work,
and to Jouni Malinen for writing wpa_ctrl.c and wpa_ctrl.h.
* src/Makefile.am
src/wpa_ctrl.[ch]
- Add wpa_ctrl stuff from wpa_supplicant so we can talk to it
* src/NetworkManagerUtils.[ch]
- (nm_utils_supplicant_request, nm_utils_supplicant_request_with_check):
Add convenience functions for talking to wpa_supplicant
* src/nm-ap-security.[ch]
src/nm-ap-security-wep.c
src/nm-ap-security-wpa-psk.[ch]
- Update and implement real_write_supplicant_config functions
in all security types
- (nm_ap_security_wpa_psk_new_from_ap): implement in
nm-ap-security-wpa-psk.c
* src/nm-device-802-11-wireless.c
- (supplicant_cleanup, supplicant_watch_cb, supplicant_monitor_status_cb,
wpa_supplicant_start, wpa_supplicant_interface_init,
wpa_supplicant_send_network_config): add functions to talk to
wpa_supplicant and write network config to it
2006-01-04 Robert Love <rml@novell.com>
* src/NetworkManagerDialup.h: add 'type' field and NM_DIALUP_TYPE

View File

@@ -59,7 +59,9 @@ NetworkManager_SOURCES = \
nm-ap-security-wpa-psk.c \
nm-ap-security-wpa-psk.h \
wpa.c \
wpa.h
wpa.h \
wpa_ctrl.c \
wpa_ctrl.h
NetworkManager_CPPFLAGS = \
$(DBUS_CFLAGS) \

View File

@@ -39,6 +39,7 @@
#include "nm-device.h"
#include "nm-device-802-11-wireless.h"
#include "nm-device-802-3-ethernet.h"
#include "wpa_ctrl.h"
#include <netlink/addr.h>
#include <netinet/in.h>
@@ -698,3 +699,84 @@ int nm_utils_ip4_netmask_to_prefix (guint32 ip4_netmask)
return (32 - (i-1));
}
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 (2048);
wpa_ctrl_request (ctrl, command, strlen (command), response, &len, NULL);
g_free (command);
response[len] = '\0';
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 (2048);
wpa_ctrl_request (ctrl, command, strlen (command), response, &len, NULL);
response[len] = '\0';
if (response)
{
if (strncmp (response, expected, strlen (expected)) == 0)
success = TRUE;
else
{
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

@@ -106,4 +106,15 @@ struct nl_addr * nm_utils_ip4_addr_to_nl_addr (guint32 ip4_addr);
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

View File

@@ -29,6 +29,8 @@
#include "nm-ap-security-private.h"
#include "dbus-helpers.h"
#include "nm-device-802-11-wireless.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
#define NM_AP_SECURITY_WEP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_WEP, NMAPSecurityWEPPrivate))
@@ -105,10 +107,38 @@ real_serialize (NMAPSecurity *instance, DBusMessageIter *iter)
return 0;
}
static void
real_write_wpa_supplicant_config (NMAPSecurity *instance, int fd)
static gboolean
real_write_supplicant_config (NMAPSecurity *instance,
struct wpa_ctrl *ctrl,
int nwid)
{
NMAPSecurityWEP * self = NM_AP_SECURITY_WEP (instance);
NMAPSecurityWEP * self = NM_AP_SECURITY_WEP (instance);
gboolean success = FALSE;
char * msg = NULL;
const char * key = nm_ap_security_get_key (instance);
/* WEP network setup */
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i key_mgmt NONE", nwid))
goto out;
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;
}
g_free (msg);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i wep_tx_keyidx 0", nwid))
goto out;
success = TRUE;
out:
return success;
}
static int
@@ -147,7 +177,7 @@ nm_ap_security_wep_class_init (NMAPSecurityWEPClass *klass)
par_class->copy_constructor_func = real_copy_constructor;
par_class->serialize_func = real_serialize;
par_class->write_wpa_supplicant_config_func = real_write_wpa_supplicant_config;
par_class->write_supplicant_config_func = real_write_supplicant_config;
par_class->device_setup_func = real_device_setup;
g_type_class_add_private (object_class, sizeof (NMAPSecurityWEPPrivate));

View File

@@ -29,6 +29,7 @@
#include "nm-ap-security-private.h"
#include "dbus-helpers.h"
#include "nm-device-802-11-wireless.h"
#include "NetworkManagerUtils.h"
#define NM_AP_SECURITY_WPA_PSK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP_SECURITY_WPA_PSK, NMAPSecurityWPA_PSKPrivate))
@@ -38,6 +39,16 @@ struct _NMAPSecurityWPA_PSKPrivate
int key_mgt;
};
static void set_description (NMAPSecurityWPA_PSK *security)
{
NMAPSecurity * parent = NM_AP_SECURITY (security);
if (nm_ap_security_get_we_cipher (parent) == IW_AUTH_CIPHER_TKIP)
nm_ap_security_set_description (parent, _("WPA TKIP"));
else
nm_ap_security_set_description (parent, _("WPA CCMP"));
}
NMAPSecurityWPA_PSK *
nm_ap_security_wpa_psk_new_deserialize (DBusMessageIter *iter, int we_cipher)
{
@@ -61,15 +72,36 @@ nm_ap_security_wpa_psk_new_deserialize (DBusMessageIter *iter, int we_cipher)
security->priv->wpa_version = wpa_version;
security->priv->key_mgt = key_mgt;
if (we_cipher == IW_AUTH_CIPHER_TKIP)
nm_ap_security_set_description (NM_AP_SECURITY (security), _("WPA TKIP"));
else
nm_ap_security_set_description (NM_AP_SECURITY (security), _("WPA CCMP"));
set_description (security);
out:
return security;
}
NMAPSecurityWPA_PSK *
nm_ap_security_wpa_psk_new_from_ap (NMAccessPoint *ap, int we_cipher)
{
NMAPSecurityWPA_PSK * security = NULL;
guint32 caps;
g_return_val_if_fail (ap != NULL, NULL);
g_return_val_if_fail (we_cipher == IW_AUTH_CIPHER_TKIP || (we_cipher == IW_AUTH_CIPHER_CCMP), NULL);
security = g_object_new (NM_TYPE_AP_SECURITY_WPA_PSK, NULL);
nm_ap_security_set_we_cipher (NM_AP_SECURITY (security), we_cipher);
caps = nm_ap_get_capabilities (ap);
if (caps & NM_802_11_CAP_PROTO_WPA2)
security->priv->wpa_version = IW_AUTH_WPA_VERSION_WPA2;
else if (caps & NM_802_11_CAP_PROTO_WPA)
security->priv->wpa_version = IW_AUTH_WPA_VERSION_WPA;
security->priv->key_mgt = IW_AUTH_KEY_MGMT_PSK;
set_description (security);
return security;
}
static int
real_serialize (NMAPSecurity *instance, DBusMessageIter *iter)
{
@@ -83,10 +115,71 @@ real_serialize (NMAPSecurity *instance, DBusMessageIter *iter)
return 0;
}
static void
real_write_wpa_supplicant_config (NMAPSecurity *instance, int fd)
static gboolean
real_write_supplicant_config (NMAPSecurity *instance,
struct wpa_ctrl *ctrl,
int nwid)
{
NMAPSecurityWPA_PSK * self = NM_AP_SECURITY_WPA_PSK (instance);
gboolean success = FALSE;
char * msg = NULL;
const char * key = nm_ap_security_get_key (instance);
int cipher = nm_ap_security_get_we_cipher (instance);
/* WPA-PSK network setup */
/* wpa_cli -ieth1 set_network 0 key_mgmt WPA-PSK */
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i key_mgmt WPA-PSK", nwid))
goto out;
msg = g_strdup_printf ("SET_NETWORK %i psk <key>", nwid);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, msg,
"SET_NETWORK %i psk %s", nwid, key))
{
g_free (msg);
goto out;
}
g_free (msg);
if (cipher == IW_AUTH_CIPHER_TKIP)
{
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i pairwise TKIP", nwid))
goto out;
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i group TKIP", nwid))
goto out;
}
else
{
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i pairwise CCMP", nwid))
goto out;
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i group CCMP", nwid))
goto out;
}
if (self->priv->wpa_version == IW_AUTH_WPA_VERSION_WPA)
{
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i proto WPA", nwid))
goto out;
}
else if (self->priv->wpa_version == IW_AUTH_WPA_VERSION_WPA2)
{
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i proto WPA2", nwid))
goto out;
}
success = TRUE;
out:
return success;
}
static int
@@ -124,7 +217,7 @@ nm_ap_security_wpa_psk_class_init (NMAPSecurityWPA_PSKClass *klass)
par_class->copy_constructor_func = real_copy_constructor;
par_class->serialize_func = real_serialize;
par_class->write_wpa_supplicant_config_func = real_write_wpa_supplicant_config;
par_class->write_supplicant_config_func = real_write_supplicant_config;
par_class->device_setup_func = real_device_setup;
g_type_class_add_private (object_class, sizeof (NMAPSecurityWPA_PSKPrivate));

View File

@@ -55,4 +55,7 @@ GType nm_ap_security_wpa_psk_get_type (void);
NMAPSecurityWPA_PSK * nm_ap_security_wpa_psk_new_deserialize (DBusMessageIter *iter, int we_cipher);
struct NMAccessPoint;
NMAPSecurityWPA_PSK * nm_ap_security_wpa_psk_new_from_ap (struct NMAccessPoint *ap, int we_cipher);
#endif /* NM_AP_SECURITY_WPA_PSK_H */

View File

@@ -29,6 +29,9 @@
#include "nm-ap-security-wep.h"
#include "nm-ap-security-wpa-psk.h"
#include "nm-device-802-11-wireless.h"
#include "wpa_ctrl.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))
@@ -112,17 +115,11 @@ nm_ap_security_new_from_ap (NMAccessPoint *ap)
/* Deteremine best encryption algorithm to use */
caps = nm_ap_get_capabilities (ap);
/*
if (caps & WPA2_CCMP_PSK)
stuff
else if (caps & WPA2_TKIP_PSK)
stuff
else if (caps & WPA_TKIP_PSK)
stuff
else
*/
if (caps & WEP_WEP104)
security = NM_AP_SECURITY (nm_ap_security_wpa_psk_new_from_ap (ap, IW_AUTH_CIPHER_CCMP));
else if ((caps & WPA_TKIP_PSK) || (caps & WPA2_TKIP_PSK))
security = NM_AP_SECURITY (nm_ap_security_wpa_psk_new_from_ap (ap, IW_AUTH_CIPHER_TKIP));
else if (caps & WEP_WEP104)
security = NM_AP_SECURITY (nm_ap_security_wep_new_from_ap (ap, IW_AUTH_CIPHER_WEP104));
else if (caps & WEP_WEP40)
security = NM_AP_SECURITY (nm_ap_security_wep_new_from_ap (ap, IW_AUTH_CIPHER_WEP40));
@@ -132,16 +129,20 @@ nm_ap_security_new_from_ap (NMAccessPoint *ap)
return security;
}
void
nm_ap_security_write_wpa_supplicant_config (NMAPSecurity *self, int fd)
gboolean
nm_ap_security_write_supplicant_config (NMAPSecurity *self,
struct wpa_ctrl *ctrl,
int nwid)
{
g_return_if_fail (self != NULL);
g_return_if_fail (fd >= 0);
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (ctrl != NULL, FALSE);
g_return_val_if_fail (nwid >= 0, FALSE);
if (self->priv->dispose_has_run)
return;
return FALSE;
NM_AP_SECURITY_GET_CLASS (self)->write_wpa_supplicant_config_func (self, fd);
return NM_AP_SECURITY_GET_CLASS (self)->write_supplicant_config_func (self, ctrl, nwid);
}
void
@@ -189,9 +190,17 @@ real_serialize (NMAPSecurity *self, DBusMessageIter *iter)
return 0;
}
static void
real_write_wpa_supplicant_config (NMAPSecurity *self, int fd)
static gboolean
real_write_supplicant_config (NMAPSecurity *self,
struct wpa_ctrl *ctrl,
int nwid)
{
/* Unencrypted network setup */
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i key_mgmt NONE", nwid))
return FALSE;
return TRUE;
}
static int
@@ -352,7 +361,7 @@ nm_ap_security_class_init (NMAPSecurityClass *klass)
klass->copy_constructor_func = real_copy_constructor;
klass->serialize_func = real_serialize;
klass->write_wpa_supplicant_config_func = real_write_wpa_supplicant_config;
klass->write_supplicant_config_func = real_write_supplicant_config;
klass->device_setup_func = real_device_setup;
g_type_class_add_private (object_class, sizeof (NMAPSecurityPrivate));

View File

@@ -53,6 +53,7 @@ struct _NMAPSecurity
};
struct NMAccessPoint;
struct wpa_ctrl;
struct _NMAPSecurityClass
{
@@ -63,7 +64,7 @@ struct _NMAPSecurityClass
int (*serialize_func) (NMAPSecurity *self, DBusMessageIter *iter);
void (*write_wpa_supplicant_config_func)(NMAPSecurity *self, int fd);
gboolean (*write_supplicant_config_func)(NMAPSecurity *self, struct wpa_ctrl *ctrl, int nwid);
int (*device_setup_func) (NMAPSecurity *self, NMDevice80211Wireless * dev);
};
@@ -83,7 +84,7 @@ const char * nm_ap_security_get_key (NMAPSecurity *self);
int nm_ap_security_serialize (NMAPSecurity *self, DBusMessageIter *iter);
void nm_ap_security_write_wpa_supplicant_config (NMAPSecurity *self, int fd);
gboolean nm_ap_security_write_supplicant_config (NMAPSecurity *self, struct wpa_ctrl *ctrl, int nwid);
int nm_ap_security_device_setup (NMAPSecurity *self, NMDevice80211Wireless *dev);

View File

@@ -26,6 +26,8 @@
#include <string.h>
#include <net/ethernet.h>
#include <iwlib.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "nm-device.h"
#include "nm-device-802-11-wireless.h"
@@ -37,6 +39,7 @@
#include "NetworkManagerPolicy.h"
#include "nm-activation-request.h"
#include "nm-dbus-nmi.h"
#include "wpa_ctrl.h"
/* #define IW_QUAL_DEBUG */
@@ -64,6 +67,12 @@ struct _NMDevice80211WirelessPrivate
guint8 scan_interval; /* seconds */
guint32 last_scan;
/* Supplicant control */
GPid sup_pid;
GSource * sup_watch;
GSource * sup_status;
struct wpa_ctrl * sup_ctrl;
/* Static options from driver */
guint8 we_version;
guint32 capabilities;
@@ -207,6 +216,7 @@ nm_device_802_11_wireless_init (NMDevice80211Wireless * self)
self->priv->dispose_has_run = FALSE;
memset (&(self->priv->hw_addr), 0, sizeof (struct ether_addr));
self->priv->sup_pid = -1;
}
static void
@@ -2335,6 +2345,224 @@ wireless_configure_infra (NMDevice80211Wireless *self,
}
/****************************************************************************/
/* WPA Supplicant control stuff
*
* Originally from:
*
* wpa_supplicant wrapper
*
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 of the License.
*/
#define WPA_SUPPLICANT_GLOBAL_SOCKET "/var/run/wpa_supplicant-global"
#define WPA_SUPPLICANT_CONTROL_SOCKET "/var/run/wpa_supplicant"
#define WPA_SUPPLICANT_BINARY "/usr/sbin/wpa_supplicant"
static void
supplicant_cleanup (NMDevice80211Wireless *self)
{
g_return_if_fail (self != NULL);
self->priv->sup_pid = -1;
if (self->priv->sup_watch)
{
g_source_destroy (self->priv->sup_watch);
self->priv->sup_watch = NULL;
}
if (self->priv->sup_status)
{
g_source_destroy (self->priv->sup_status);
self->priv->sup_status = NULL;
}
if (self->priv->sup_ctrl)
{
wpa_ctrl_close (self->priv->sup_ctrl);
self->priv->sup_ctrl = NULL;
}
}
static void
supplicant_watch_cb (GPid pid,
gint status,
gpointer user_data)
{
NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
g_assert (self);
if (WIFEXITED (status))
nm_warning ("wpa_supplicant exited with error code %d", WEXITSTATUS (status));
else if (WIFSTOPPED (status))
nm_warning ("wpa_supplicant stopped unexpectedly with signal %d", WSTOPSIG (status));
else if (WIFSIGNALED (status))
nm_warning ("wpa_supplicant died with signal %d", WTERMSIG (status));
else
nm_warning ("wpa_supplicant died from an unknown cause");
supplicant_cleanup (self);
/* FIXME: deal with disconnection; device no longer has a link */
}
static gboolean
supplicant_monitor_status_cb (GIOChannel *source,
GIOCondition condition,
gpointer user_data)
{
NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
char message[2048];
size_t message_len;
struct wpa_ctrl * ctrl;
g_assert (self);
ctrl = self->priv->sup_ctrl;
g_return_val_if_fail (ctrl != NULL, FALSE);
message_len = sizeof (message);
wpa_ctrl_recv (ctrl, message, &message_len);
message[message_len] = '\0';
if (strstr (message, WPA_EVENT_CONNECTED) != NULL)
printf("UP\n");
else if (strstr (message, WPA_EVENT_DISCONNECTED) != NULL)
printf("DOWN\n");
return TRUE;
}
static gboolean
wpa_supplicant_start (NMDevice80211Wireless *self)
{
gboolean success = FALSE;
char * argv[4];
GError * error;
GPid pid = -1;
argv[0] = WPA_SUPPLICANT_BINARY;
argv[1] = "-g";
argv[2] = WPA_SUPPLICANT_GLOBAL_SOCKET;
argv[4] = NULL;
if (!(success = g_spawn_async ("/", argv, NULL, 0, NULL, NULL, &pid, &error)))
{
if (error)
{
nm_warning ("Couldn't start wpa_supplicant. Error: (%d) %s",
error->code, error->message);
g_error_free (error);
}
else
nm_warning ("Couldn't start wpa_supplicant due to an unknown error.");
}
else
{
if (self->priv->sup_watch)
g_source_destroy (self->priv->sup_watch);
self->priv->sup_watch = g_child_watch_source_new (pid);
g_source_set_callback (self->priv->sup_watch, (GSourceFunc) supplicant_watch_cb, self, NULL);
g_source_attach (self->priv->sup_watch, nm_device_get_main_context (NM_DEVICE (self)));
}
return success;
}
static gboolean
wpa_supplicant_interface_init (NMDevice80211Wireless *self)
{
struct wpa_ctrl * ctrl;
struct wpa_ctrl * ctrl_if = NULL;
char * socket_path;
const char * iface = nm_device_get_iface (NM_DEVICE (self));
gboolean success = FALSE;
if (!(ctrl = wpa_ctrl_open (WPA_SUPPLICANT_GLOBAL_SOCKET)))
goto exit;
/* wpa_cli -g/var/run/wpa_supplicant-global interface_add eth1 "" wext /var/run/wpa_supplicant */
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"INTERFACE_ADD %s\t\twext\t" WPA_SUPPLICANT_CONTROL_SOCKET "\t", iface))
goto exit;
wpa_ctrl_close (ctrl);
/* attach to interface socket */
if (!(socket_path = g_strdup_printf (WPA_SUPPLICANT_CONTROL_SOCKET "/%s", iface)))
goto exit;
self->priv->sup_ctrl = wpa_ctrl_open (socket_path);
g_free (socket_path);
success = TRUE;
exit:
return success;
}
static gboolean
wpa_supplicant_send_network_config (NMDevice80211Wireless *self,
NMActRequest *req)
{
NMAccessPoint * ap = NULL;
gboolean success = FALSE;
char * response = NULL;
int nwid;
const char * essid;
struct wpa_ctrl * ctrl;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (req != NULL, FALSE);
ap = nm_act_request_get_ap (req);
g_assert (ap);
ctrl = self->priv->sup_ctrl;
g_assert (ctrl);
/* Standard network setup info */
if (!(response = nm_utils_supplicant_request (ctrl, "ADD_NETWORK")))
{
nm_warning ("Supplicant error for ADD_NETWORK.\n");
goto out;
}
if (sscanf (response, "%i\n", &nwid) != 1)
{
nm_warning ("Supplicant error for ADD_NETWORK. Response: '%s'\n", response);
g_free (response);
goto out;
}
g_free (response);
if (nm_device_activation_should_cancel (NM_DEVICE (self)))
goto out;
essid = nm_ap_get_essid (ap);
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"SET_NETWORK %i ssid \"%s\"", nwid, essid))
goto out;
if (nm_device_activation_should_cancel (NM_DEVICE (self)))
goto out;
if (!nm_ap_security_write_supplicant_config (nm_ap_get_security (ap), ctrl, nwid))
goto out;
if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
"ENABLE_NETWORK %i", nwid, essid))
goto out;
success = TRUE;
out:
return success;
}
/****************************************************************************/
static NMActStageReturn
real_act_stage2_config (NMDevice *dev,
NMActRequest *req)

240
src/wpa_ctrl.c Normal file
View File

@@ -0,0 +1,240 @@
/*
* 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)
{
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),
"/tmp/wpa_ctrl_%d-%d", 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 */

185
src/wpa_ctrl.h Normal file
View File

@@ -0,0 +1,185 @@
/*
* 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);
/**
* 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 */